|  | @@ -3608,245 +3608,6 @@ TEST_P(LdsRdsTest, XdsRoutingHeadersMatching) {
 | 
	
		
			
				|  |  |    gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialHeaderContentType) {
 | 
	
		
			
				|  |  | -  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
 | 
	
		
			
				|  |  | -  const char* kNewCluster1Name = "new_cluster_1";
 | 
	
		
			
				|  |  | -  const size_t kNumEchoRpcs = 100;
 | 
	
		
			
				|  |  | -  SetNextResolution({});
 | 
	
		
			
				|  |  | -  SetNextResolutionForLbChannelAllBalancers();
 | 
	
		
			
				|  |  | -  // Populate new EDS resources.
 | 
	
		
			
				|  |  | -  AdsServiceImpl::EdsResourceArgs args({
 | 
	
		
			
				|  |  | -      {"locality0", GetBackendPorts(0, 1)},
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  AdsServiceImpl::EdsResourceArgs args1({
 | 
	
		
			
				|  |  | -      {"locality0", GetBackendPorts(1, 2)},
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  balancers_[0]->ads_service()->SetEdsResource(
 | 
	
		
			
				|  |  | -      AdsServiceImpl::BuildEdsResource(args));
 | 
	
		
			
				|  |  | -  balancers_[0]->ads_service()->SetEdsResource(
 | 
	
		
			
				|  |  | -      AdsServiceImpl::BuildEdsResource(args1, kNewCluster1Name));
 | 
	
		
			
				|  |  | -  // Populate new CDS resources.
 | 
	
		
			
				|  |  | -  Cluster new_cluster1 = balancers_[0]->ads_service()->default_cluster();
 | 
	
		
			
				|  |  | -  new_cluster1.set_name(kNewCluster1Name);
 | 
	
		
			
				|  |  | -  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
 | 
	
		
			
				|  |  | -  // Populating Route Configurations for LDS.
 | 
	
		
			
				|  |  | -  RouteConfiguration route_config =
 | 
	
		
			
				|  |  | -      balancers_[0]->ads_service()->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(kNewCluster1Name);
 | 
	
		
			
				|  |  | -  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(kDefaultResourceName);
 | 
	
		
			
				|  |  | -  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);
 | 
	
		
			
				|  |  | -  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialHeaderUserAgent) {
 | 
	
		
			
				|  |  | -  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
 | 
	
		
			
				|  |  | -  const char* kNewCluster1Name = "new_cluster_1";
 | 
	
		
			
				|  |  | -  const size_t kNumEchoRpcs = 100;
 | 
	
		
			
				|  |  | -  SetNextResolution({});
 | 
	
		
			
				|  |  | -  SetNextResolutionForLbChannelAllBalancers();
 | 
	
		
			
				|  |  | -  // Populate new EDS resources.
 | 
	
		
			
				|  |  | -  AdsServiceImpl::EdsResourceArgs args({
 | 
	
		
			
				|  |  | -      {"locality0", GetBackendPorts(0, 1)},
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  AdsServiceImpl::EdsResourceArgs args1({
 | 
	
		
			
				|  |  | -      {"locality0", GetBackendPorts(1, 2)},
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  balancers_[0]->ads_service()->SetEdsResource(
 | 
	
		
			
				|  |  | -      AdsServiceImpl::BuildEdsResource(args));
 | 
	
		
			
				|  |  | -  balancers_[0]->ads_service()->SetEdsResource(
 | 
	
		
			
				|  |  | -      AdsServiceImpl::BuildEdsResource(args1, kNewCluster1Name));
 | 
	
		
			
				|  |  | -  // Populate new CDS resources.
 | 
	
		
			
				|  |  | -  Cluster new_cluster1 = balancers_[0]->ads_service()->default_cluster();
 | 
	
		
			
				|  |  | -  new_cluster1.set_name(kNewCluster1Name);
 | 
	
		
			
				|  |  | -  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
 | 
	
		
			
				|  |  | -  // Populating Route Configurations for LDS.
 | 
	
		
			
				|  |  | -  RouteConfiguration route_config =
 | 
	
		
			
				|  |  | -      balancers_[0]->ads_service()->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("user-agent");
 | 
	
		
			
				|  |  | -  header_matcher1->mutable_safe_regex_match()->set_regex(
 | 
	
		
			
				|  |  | -      "(does-not-match-grpc-c).*");
 | 
	
		
			
				|  |  | -  route1->mutable_route()->set_cluster(kNewCluster1Name);
 | 
	
		
			
				|  |  | -  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("user-agent");
 | 
	
		
			
				|  |  | -  // user-agent string is a 2-part string like "grpc-c++/1.31.0-dev
 | 
	
		
			
				|  |  | -  // grpc-c/11.0.0".
 | 
	
		
			
				|  |  | -  header_matcher2->mutable_safe_regex_match()->set_regex(
 | 
	
		
			
				|  |  | -      "((grpc-c).*[0-9]+.[0-9]+.[0-9]+.*){2}");
 | 
	
		
			
				|  |  | -  default_route->mutable_route()->set_cluster(kDefaultResourceName);
 | 
	
		
			
				|  |  | -  SetRouteConfiguration(0, route_config);
 | 
	
		
			
				|  |  | -  // Make sure 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);
 | 
	
		
			
				|  |  | -  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialHeaderGrpcTimeout) {
 | 
	
		
			
				|  |  | -  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
 | 
	
		
			
				|  |  | -  const char* kNewCluster1Name = "new_cluster_1";
 | 
	
		
			
				|  |  | -  const size_t kNumEchoRpcs = 100;
 | 
	
		
			
				|  |  | -  SetNextResolution({});
 | 
	
		
			
				|  |  | -  SetNextResolutionForLbChannelAllBalancers();
 | 
	
		
			
				|  |  | -  // Populate new EDS resources.
 | 
	
		
			
				|  |  | -  AdsServiceImpl::EdsResourceArgs args({
 | 
	
		
			
				|  |  | -      {"locality0", GetBackendPorts(0, 1)},
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  AdsServiceImpl::EdsResourceArgs args1({
 | 
	
		
			
				|  |  | -      {"locality0", GetBackendPorts(1, 2)},
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  balancers_[0]->ads_service()->SetEdsResource(
 | 
	
		
			
				|  |  | -      AdsServiceImpl::BuildEdsResource(args));
 | 
	
		
			
				|  |  | -  balancers_[0]->ads_service()->SetEdsResource(
 | 
	
		
			
				|  |  | -      AdsServiceImpl::BuildEdsResource(args1, kNewCluster1Name));
 | 
	
		
			
				|  |  | -  // Populate new CDS resources.
 | 
	
		
			
				|  |  | -  Cluster new_cluster1 = balancers_[0]->ads_service()->default_cluster();
 | 
	
		
			
				|  |  | -  new_cluster1.set_name(kNewCluster1Name);
 | 
	
		
			
				|  |  | -  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
 | 
	
		
			
				|  |  | -  // Populating Route Configurations for LDS.
 | 
	
		
			
				|  |  | -  RouteConfiguration route_config =
 | 
	
		
			
				|  |  | -      balancers_[0]->ads_service()->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-timeout");
 | 
	
		
			
				|  |  | -  header_matcher1->mutable_safe_regex_match()->set_regex("[0-9]+(s|h)");
 | 
	
		
			
				|  |  | -  route1->mutable_route()->set_cluster(kNewCluster1Name);
 | 
	
		
			
				|  |  | -  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("grpc-timeout");
 | 
	
		
			
				|  |  | -  header_matcher2->mutable_safe_regex_match()->set_regex("[0-9]+(m|S|M|H)");
 | 
	
		
			
				|  |  | -  default_route->mutable_route()->set_cluster(kDefaultResourceName);
 | 
	
		
			
				|  |  | -  SetRouteConfiguration(0, route_config);
 | 
	
		
			
				|  |  | -  // Make sure 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);
 | 
	
		
			
				|  |  | -  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialCasesToIgnore) {
 | 
	
		
			
				|  |  | -  gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
 | 
	
		
			
				|  |  | -  const char* kNewCluster1Name = "new_cluster_1";
 | 
	
		
			
				|  |  | -  const char* kNewCluster2Name = "new_cluster_2";
 | 
	
		
			
				|  |  | -  const char* kNewCluster3Name = "new_cluster_3";
 | 
	
		
			
				|  |  | -  const size_t kNumEcho1Rpcs = 100;
 | 
	
		
			
				|  |  | -  const size_t kNumEchoRpcs = 5;
 | 
	
		
			
				|  |  | -  SetNextResolution({});
 | 
	
		
			
				|  |  | -  SetNextResolutionForLbChannelAllBalancers();
 | 
	
		
			
				|  |  | -  // Populate new EDS resources.
 | 
	
		
			
				|  |  | -  AdsServiceImpl::EdsResourceArgs args({
 | 
	
		
			
				|  |  | -      {"locality0", GetBackendPorts(0, 1)},
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  AdsServiceImpl::EdsResourceArgs args1({
 | 
	
		
			
				|  |  | -      {"locality0", GetBackendPorts(1, 2)},
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  AdsServiceImpl::EdsResourceArgs args2({
 | 
	
		
			
				|  |  | -      {"locality0", GetBackendPorts(2, 3)},
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  AdsServiceImpl::EdsResourceArgs args3({
 | 
	
		
			
				|  |  | -      {"locality0", GetBackendPorts(3, 4)},
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  balancers_[0]->ads_service()->SetEdsResource(
 | 
	
		
			
				|  |  | -      AdsServiceImpl::BuildEdsResource(args));
 | 
	
		
			
				|  |  | -  balancers_[0]->ads_service()->SetEdsResource(
 | 
	
		
			
				|  |  | -      AdsServiceImpl::BuildEdsResource(args1, kNewCluster1Name));
 | 
	
		
			
				|  |  | -  balancers_[0]->ads_service()->SetEdsResource(
 | 
	
		
			
				|  |  | -      AdsServiceImpl::BuildEdsResource(args2, kNewCluster2Name));
 | 
	
		
			
				|  |  | -  balancers_[0]->ads_service()->SetEdsResource(
 | 
	
		
			
				|  |  | -      AdsServiceImpl::BuildEdsResource(args3, kNewCluster3Name));
 | 
	
		
			
				|  |  | -  // Populate new CDS resources.
 | 
	
		
			
				|  |  | -  Cluster new_cluster1 = balancers_[0]->ads_service()->default_cluster();
 | 
	
		
			
				|  |  | -  new_cluster1.set_name(kNewCluster1Name);
 | 
	
		
			
				|  |  | -  balancers_[0]->ads_service()->SetCdsResource(new_cluster1);
 | 
	
		
			
				|  |  | -  Cluster new_cluster2 = balancers_[0]->ads_service()->default_cluster();
 | 
	
		
			
				|  |  | -  new_cluster2.set_name(kNewCluster2Name);
 | 
	
		
			
				|  |  | -  balancers_[0]->ads_service()->SetCdsResource(new_cluster2);
 | 
	
		
			
				|  |  | -  Cluster new_cluster3 = balancers_[0]->ads_service()->default_cluster();
 | 
	
		
			
				|  |  | -  new_cluster1.set_name(kNewCluster3Name);
 | 
	
		
			
				|  |  | -  balancers_[0]->ads_service()->SetCdsResource(new_cluster3);
 | 
	
		
			
				|  |  | -  // Populating Route Configurations for LDS.
 | 
	
		
			
				|  |  | -  RouteConfiguration route_config =
 | 
	
		
			
				|  |  | -      balancers_[0]->ads_service()->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("grpc-tags-bin");
 | 
	
		
			
				|  |  | -  header_matcher1->set_exact_match("grpc-tags-bin");
 | 
	
		
			
				|  |  | -  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("grpc-trace-bin");
 | 
	
		
			
				|  |  | -  header_matcher2->set_exact_match("grpc-trace-bin");
 | 
	
		
			
				|  |  | -  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("grpc-previous-rpc-attempts");
 | 
	
		
			
				|  |  | -  header_matcher3->set_exact_match("grpc-previous-rpc-attempts");
 | 
	
		
			
				|  |  | -  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(kDefaultResourceName);
 | 
	
		
			
				|  |  | -  SetRouteConfiguration(0, route_config);
 | 
	
		
			
				|  |  | -  // Send headers which will mismatch each route
 | 
	
		
			
				|  |  | -  std::vector<std::pair<std::string, std::string>> metadata = {
 | 
	
		
			
				|  |  | -      {"grpc-tags-bin", "grpc-tags-bin"},
 | 
	
		
			
				|  |  | -      {"grpc-trace-bin", "grpc-trace-bin"},
 | 
	
		
			
				|  |  | -      {"grpc-previous-rpc-attempts", "grpc-previous-rpc-attempts"},
 | 
	
		
			
				|  |  | -  };
 | 
	
		
			
				|  |  | -  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);
 | 
	
		
			
				|  |  | -  gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING");
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  |  TEST_P(LdsRdsTest, XdsRoutingRuntimeFractionMatching) {
 | 
	
		
			
				|  |  |    gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true");
 | 
	
		
			
				|  |  |    const char* kNewCluster1Name = "new_cluster_1";
 |