xds: Fix cluster selection races when updating config selector

Listener2.onResult() doesn't require running in the sync context, so
when called from the sync context it is guaranteed not to do its
processing immediately (instead, it schedules work into the sync
context).

The code was doing an update dance: 1) update service config to add new
cluster, 2) update config selector to use new cluster, 3) update service
config to remove old clusters. But the onResult() wasn't being processed
immediately, so the actual execution order was 2, 1, 3 which has a small
window where RPCs will fail. But onResult2() does run immediately. And
since ca4819ac6, updateBalancingState() updates the picker immediately.

cleanUpRoutes() was also racy because it updated the routingConfig
before swapping to the new config selector, so RPCs could fail saying
there was no route instead of the useful error message. Even with the
opposite order, some RPCs may be executing the while loop of
selectConfig(), trying to acquire a cluster. The code unreffed the
clusters before updating the routingConfig, so those RPCs could go into
a tight loop until the routingConfig was updated. Also, once the
routingConfig was updated to EMPTY those RPCs would similarly
see the wrong error message. To give the correct error message,
selectConfig() must fail such RPCs directly, and once it can do that
there's no need to stop using the config selector in error cases. This
has the benefit of fewer moving parts and more consistent threading
among cases.

The added test was able to detect the race 2% of the time. The slower
the code/machine, the more reliable the test failed. ca4819ac6 along
with this commit reduced it to 0 failures in 1000 runs.

Discovered when investigating b/394850611
This commit is contained in:
Eric Anderson 2025-03-07 10:33:35 -08:00 committed by GitHub
parent ca4819ac6d
commit d82613a74c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 177 additions and 84 deletions

View File

@ -132,7 +132,7 @@ final class XdsNameResolver extends NameResolver {
// NamedFilterConfig.filterStateKey -> filter_instance. // NamedFilterConfig.filterStateKey -> filter_instance.
private final HashMap<String, Filter> activeFilters = new HashMap<>(); private final HashMap<String, Filter> activeFilters = new HashMap<>();
private volatile RoutingConfig routingConfig = RoutingConfig.EMPTY; private volatile RoutingConfig routingConfig;
private Listener2 listener; private Listener2 listener;
private ObjectPool<XdsClient> xdsClientPool; private ObjectPool<XdsClient> xdsClientPool;
private XdsClient xdsClient; private XdsClient xdsClient;
@ -306,7 +306,7 @@ final class XdsNameResolver extends NameResolver {
if (logger.isLoggable(XdsLogLevel.INFO)) { if (logger.isLoggable(XdsLogLevel.INFO)) {
logger.log( logger.log(
XdsLogLevel.INFO, "Generated service config:\n{0}", new Gson().toJson(rawServiceConfig)); XdsLogLevel.INFO, "Generated service config: {0}", new Gson().toJson(rawServiceConfig));
} }
ConfigOrError parsedServiceConfig = serviceConfigParser.parseServiceConfig(rawServiceConfig); ConfigOrError parsedServiceConfig = serviceConfigParser.parseServiceConfig(rawServiceConfig);
Attributes attrs = Attributes attrs =
@ -320,7 +320,7 @@ final class XdsNameResolver extends NameResolver {
.setAttributes(attrs) .setAttributes(attrs)
.setServiceConfig(parsedServiceConfig) .setServiceConfig(parsedServiceConfig)
.build(); .build();
listener.onResult(result); listener.onResult2(result);
receivedConfig = true; receivedConfig = true;
} }
@ -395,6 +395,9 @@ final class XdsNameResolver extends NameResolver {
String path = "/" + args.getMethodDescriptor().getFullMethodName(); String path = "/" + args.getMethodDescriptor().getFullMethodName();
do { do {
routingCfg = routingConfig; routingCfg = routingConfig;
if (routingCfg.errorStatus != null) {
return Result.forError(routingCfg.errorStatus);
}
selectedRoute = null; selectedRoute = null;
for (RouteData route : routingCfg.routes) { for (RouteData route : routingCfg.routes) {
if (RoutingUtils.matchRoute(route.routeMatch, path, headers, random)) { if (RoutingUtils.matchRoute(route.routeMatch, path, headers, random)) {
@ -626,19 +629,6 @@ final class XdsNameResolver extends NameResolver {
return "cluster_specifier_plugin:" + pluginName; return "cluster_specifier_plugin:" + pluginName;
} }
private static final class FailingConfigSelector extends InternalConfigSelector {
private final Result result;
public FailingConfigSelector(Status error) {
this.result = Result.forError(error);
}
@Override
public Result selectConfig(PickSubchannelArgs args) {
return result;
}
}
private class ResolveState implements ResourceWatcher<XdsListenerResource.LdsUpdate> { private class ResolveState implements ResourceWatcher<XdsListenerResource.LdsUpdate> {
private final ConfigOrError emptyServiceConfig = private final ConfigOrError emptyServiceConfig =
serviceConfigParser.parseServiceConfig(Collections.<String, Object>emptyMap()); serviceConfigParser.parseServiceConfig(Collections.<String, Object>emptyMap());
@ -835,13 +825,13 @@ final class XdsNameResolver extends NameResolver {
} }
} }
// Update service config to include newly added clusters. // Update service config to include newly added clusters.
if (shouldUpdateResult) { if (shouldUpdateResult && routingConfig != null) {
updateResolutionResult(); updateResolutionResult();
shouldUpdateResult = false;
} }
// Make newly added clusters selectable by config selector and deleted clusters no longer // Make newly added clusters selectable by config selector and deleted clusters no longer
// selectable. // selectable.
routingConfig = new RoutingConfig(httpMaxStreamDurationNano, routesData.build()); routingConfig = new RoutingConfig(httpMaxStreamDurationNano, routesData.build());
shouldUpdateResult = false;
for (String cluster : deletedClusters) { for (String cluster : deletedClusters) {
int count = clusterRefs.get(cluster).refCount.decrementAndGet(); int count = clusterRefs.get(cluster).refCount.decrementAndGet();
if (count == 0) { if (count == 0) {
@ -893,6 +883,9 @@ final class XdsNameResolver extends NameResolver {
} }
private void cleanUpRoutes(String error) { private void cleanUpRoutes(String error) {
String errorWithNodeId =
error + ", xDS node ID: " + xdsClient.getBootstrapInfo().node().getId();
routingConfig = new RoutingConfig(Status.UNAVAILABLE.withDescription(errorWithNodeId));
if (existingClusters != null) { if (existingClusters != null) {
for (String cluster : existingClusters) { for (String cluster : existingClusters) {
int count = clusterRefs.get(cluster).refCount.decrementAndGet(); int count = clusterRefs.get(cluster).refCount.decrementAndGet();
@ -902,17 +895,12 @@ final class XdsNameResolver extends NameResolver {
} }
existingClusters = null; existingClusters = null;
} }
routingConfig = RoutingConfig.EMPTY;
// Without addresses the default LB (normally pick_first) should become TRANSIENT_FAILURE, and // Without addresses the default LB (normally pick_first) should become TRANSIENT_FAILURE, and
// the config selector handles the error message itself. Once the LB API allows providing // the config selector handles the error message itself.
// failure information for addresses yet still providing a service config, the config seector listener.onResult2(ResolutionResult.newBuilder()
// could be avoided.
String errorWithNodeId =
error + ", xDS node ID: " + xdsClient.getBootstrapInfo().node().getId();
listener.onResult(ResolutionResult.newBuilder()
.setAttributes(Attributes.newBuilder() .setAttributes(Attributes.newBuilder()
.set(InternalConfigSelector.KEY, .set(InternalConfigSelector.KEY, configSelector)
new FailingConfigSelector(Status.UNAVAILABLE.withDescription(errorWithNodeId)))
.build()) .build())
.setServiceConfig(emptyServiceConfig) .setServiceConfig(emptyServiceConfig)
.build()); .build());
@ -983,12 +971,19 @@ final class XdsNameResolver extends NameResolver {
private static class RoutingConfig { private static class RoutingConfig {
private final long fallbackTimeoutNano; private final long fallbackTimeoutNano;
final ImmutableList<RouteData> routes; final ImmutableList<RouteData> routes;
final Status errorStatus;
private static final RoutingConfig EMPTY = new RoutingConfig(0, ImmutableList.of());
private RoutingConfig(long fallbackTimeoutNano, ImmutableList<RouteData> routes) { private RoutingConfig(long fallbackTimeoutNano, ImmutableList<RouteData> routes) {
this.fallbackTimeoutNano = fallbackTimeoutNano; this.fallbackTimeoutNano = fallbackTimeoutNano;
this.routes = checkNotNull(routes, "routes"); this.routes = checkNotNull(routes, "routes");
this.errorStatus = null;
}
private RoutingConfig(Status errorStatus) {
this.fallbackTimeoutNano = 0;
this.routes = null;
this.errorStatus = checkNotNull(errorStatus, "errorStatus");
checkArgument(!errorStatus.isOk(), "errorStatus should not be okay");
} }
} }

View File

@ -19,9 +19,12 @@ package io.grpc.xds;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static io.grpc.xds.DataPlaneRule.ENDPOINT_HOST_NAME; import static io.grpc.xds.DataPlaneRule.ENDPOINT_HOST_NAME;
import static io.grpc.xds.XdsTestControlPlaneService.ADS_TYPE_URL_CDS;
import static io.grpc.xds.XdsTestControlPlaneService.ADS_TYPE_URL_EDS;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import com.github.xds.type.v3.TypedStruct; import com.github.xds.type.v3.TypedStruct;
import com.google.common.collect.ImmutableMap;
import com.google.protobuf.Any; import com.google.protobuf.Any;
import com.google.protobuf.Struct; import com.google.protobuf.Struct;
import com.google.protobuf.Value; import com.google.protobuf.Value;
@ -36,11 +39,17 @@ import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment;
import io.envoyproxy.envoy.config.endpoint.v3.Endpoint; import io.envoyproxy.envoy.config.endpoint.v3.Endpoint;
import io.envoyproxy.envoy.config.endpoint.v3.LbEndpoint; import io.envoyproxy.envoy.config.endpoint.v3.LbEndpoint;
import io.envoyproxy.envoy.config.endpoint.v3.LocalityLbEndpoints; import io.envoyproxy.envoy.config.endpoint.v3.LocalityLbEndpoints;
import io.envoyproxy.envoy.config.route.v3.Route;
import io.envoyproxy.envoy.config.route.v3.RouteAction;
import io.envoyproxy.envoy.config.route.v3.RouteConfiguration;
import io.envoyproxy.envoy.config.route.v3.RouteMatch;
import io.envoyproxy.envoy.config.route.v3.VirtualHost;
import io.envoyproxy.envoy.extensions.load_balancing_policies.wrr_locality.v3.WrrLocality; import io.envoyproxy.envoy.extensions.load_balancing_policies.wrr_locality.v3.WrrLocality;
import io.grpc.CallOptions; import io.grpc.CallOptions;
import io.grpc.Channel; import io.grpc.Channel;
import io.grpc.ClientCall; import io.grpc.ClientCall;
import io.grpc.ClientInterceptor; import io.grpc.ClientInterceptor;
import io.grpc.ClientStreamTracer;
import io.grpc.ForwardingClientCall.SimpleForwardingClientCall; import io.grpc.ForwardingClientCall.SimpleForwardingClientCall;
import io.grpc.ForwardingClientCallListener; import io.grpc.ForwardingClientCallListener;
import io.grpc.LoadBalancerRegistry; import io.grpc.LoadBalancerRegistry;
@ -89,8 +98,7 @@ public class FakeControlPlaneXdsIntegrationTest {
ManagedChannel channel = dataPlane.getManagedChannel(); ManagedChannel channel = dataPlane.getManagedChannel();
SimpleServiceGrpc.SimpleServiceBlockingStub blockingStub = SimpleServiceGrpc.newBlockingStub( SimpleServiceGrpc.SimpleServiceBlockingStub blockingStub = SimpleServiceGrpc.newBlockingStub(
channel); channel);
SimpleRequest request = SimpleRequest.newBuilder() SimpleRequest request = SimpleRequest.getDefaultInstance();
.build();
SimpleResponse goldenResponse = SimpleResponse.newBuilder() SimpleResponse goldenResponse = SimpleResponse.newBuilder()
.setResponseMessage("Hi, xDS! Authority= test-server") .setResponseMessage("Hi, xDS! Authority= test-server")
.build(); .build();
@ -104,8 +112,7 @@ public class FakeControlPlaneXdsIntegrationTest {
ManagedChannel channel = dataPlane.getManagedChannel(); ManagedChannel channel = dataPlane.getManagedChannel();
SimpleServiceGrpc.SimpleServiceBlockingStub blockingStub = SimpleServiceGrpc.newBlockingStub( SimpleServiceGrpc.SimpleServiceBlockingStub blockingStub = SimpleServiceGrpc.newBlockingStub(
channel); channel);
SimpleRequest request = SimpleRequest.newBuilder() SimpleRequest request = SimpleRequest.getDefaultInstance();
.build();
SimpleResponse goldenResponse = SimpleResponse.newBuilder() SimpleResponse goldenResponse = SimpleResponse.newBuilder()
.setResponseMessage("Hi, xDS! Authority= " + ENDPOINT_HOST_NAME) .setResponseMessage("Hi, xDS! Authority= " + ENDPOINT_HOST_NAME)
.build(); .build();
@ -145,8 +152,7 @@ public class FakeControlPlaneXdsIntegrationTest {
// We add an interceptor to catch the response headers from the server. // We add an interceptor to catch the response headers from the server.
SimpleServiceGrpc.SimpleServiceBlockingStub blockingStub = SimpleServiceGrpc.newBlockingStub( SimpleServiceGrpc.SimpleServiceBlockingStub blockingStub = SimpleServiceGrpc.newBlockingStub(
dataPlane.getManagedChannel()).withInterceptors(responseHeaderInterceptor); dataPlane.getManagedChannel()).withInterceptors(responseHeaderInterceptor);
SimpleRequest request = SimpleRequest.newBuilder() SimpleRequest request = SimpleRequest.getDefaultInstance();
.build();
SimpleResponse goldenResponse = SimpleResponse.newBuilder() SimpleResponse goldenResponse = SimpleResponse.newBuilder()
.setResponseMessage("Hi, xDS! Authority= test-server") .setResponseMessage("Hi, xDS! Authority= test-server")
.build(); .build();
@ -160,6 +166,100 @@ public class FakeControlPlaneXdsIntegrationTest {
} }
} }
// Try to trigger "UNAVAILABLE: CDS encountered error: unable to find available subchannel for
// cluster cluster:cluster1" race, if XdsNameResolver updates its ConfigSelector before
// cluster_manager config.
@Test
public void changeClusterForRoute() throws Exception {
// Start with route to cluster0
InetSocketAddress edsInetSocketAddress
= (InetSocketAddress) dataPlane.getServer().getListenSockets().get(0);
controlPlane.getService().setXdsConfig(
ADS_TYPE_URL_EDS,
ImmutableMap.of(
"eds-service-0",
ControlPlaneRule.buildClusterLoadAssignment(
edsInetSocketAddress.getHostName(), "", edsInetSocketAddress.getPort(),
"eds-service-0"),
"eds-service-1",
ControlPlaneRule.buildClusterLoadAssignment(
edsInetSocketAddress.getHostName(), "", edsInetSocketAddress.getPort(),
"eds-service-1")));
controlPlane.getService().setXdsConfig(
ADS_TYPE_URL_CDS,
ImmutableMap.of(
"cluster0",
ControlPlaneRule.buildCluster("cluster0", "eds-service-0"),
"cluster1",
ControlPlaneRule.buildCluster("cluster1", "eds-service-1")));
controlPlane.setRdsConfig(RouteConfiguration.newBuilder()
.setName("route-config.googleapis.com")
.addVirtualHosts(VirtualHost.newBuilder()
.addDomains("test-server")
.addRoutes(Route.newBuilder()
.setMatch(RouteMatch.newBuilder().setPrefix("/").build())
.setRoute(RouteAction.newBuilder().setCluster("cluster0").build())
.build())
.build())
.build());
class ClusterClientStreamTracer extends ClientStreamTracer {
boolean usedCluster1;
@Override
public void addOptionalLabel(String key, String value) {
if ("grpc.lb.backend_service".equals(key)) {
usedCluster1 = "cluster1".equals(value);
}
}
}
ClusterClientStreamTracer tracer = new ClusterClientStreamTracer();
ClientStreamTracer.Factory tracerFactory = new ClientStreamTracer.Factory() {
@Override
public ClientStreamTracer newClientStreamTracer(
ClientStreamTracer.StreamInfo info, Metadata headers) {
return tracer;
}
};
ClientInterceptor tracerInterceptor = new ClientInterceptor() {
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
return next.newCall(method, callOptions.withStreamTracerFactory(tracerFactory));
}
};
SimpleServiceGrpc.SimpleServiceBlockingStub stub = SimpleServiceGrpc
.newBlockingStub(dataPlane.getManagedChannel())
.withInterceptors(tracerInterceptor);
SimpleRequest request = SimpleRequest.getDefaultInstance();
SimpleResponse goldenResponse = SimpleResponse.newBuilder()
.setResponseMessage("Hi, xDS! Authority= test-server")
.build();
assertThat(stub.unaryRpc(request)).isEqualTo(goldenResponse);
assertThat(tracer.usedCluster1).isFalse();
// Check for errors when swapping route to cluster1
controlPlane.setRdsConfig(RouteConfiguration.newBuilder()
.setName("route-config.googleapis.com")
.addVirtualHosts(VirtualHost.newBuilder()
.addDomains("test-server")
.addRoutes(Route.newBuilder()
.setMatch(RouteMatch.newBuilder().setPrefix("/").build())
.setRoute(RouteAction.newBuilder().setCluster("cluster1").build())
.build())
.build())
.build());
for (int j = 0; j < 10; j++) {
stub.unaryRpc(request);
if (tracer.usedCluster1) {
break;
}
}
assertThat(tracer.usedCluster1).isTrue();
}
// Captures response headers from the server. // Captures response headers from the server.
private static class ResponseHeaderClientInterceptor implements ClientInterceptor { private static class ResponseHeaderClientInterceptor implements ClientInterceptor {
Metadata reponseHeaders; Metadata reponseHeaders;
@ -199,8 +299,7 @@ public class FakeControlPlaneXdsIntegrationTest {
ManagedChannel channel = dataPlane.getManagedChannel(); ManagedChannel channel = dataPlane.getManagedChannel();
SimpleServiceGrpc.SimpleServiceBlockingStub blockingStub = SimpleServiceGrpc.newBlockingStub( SimpleServiceGrpc.SimpleServiceBlockingStub blockingStub = SimpleServiceGrpc.newBlockingStub(
channel); channel);
SimpleRequest request = SimpleRequest.newBuilder() SimpleRequest request = SimpleRequest.getDefaultInstance();
.build();
SimpleResponse goldenResponse = SimpleResponse.newBuilder() SimpleResponse goldenResponse = SimpleResponse.newBuilder()
.setResponseMessage("Hi, xDS! Authority= test-server") .setResponseMessage("Hi, xDS! Authority= test-server")
.build(); .build();
@ -231,8 +330,7 @@ public class FakeControlPlaneXdsIntegrationTest {
ManagedChannel channel = dataPlane.getManagedChannel(); ManagedChannel channel = dataPlane.getManagedChannel();
SimpleServiceGrpc.SimpleServiceBlockingStub blockingStub = SimpleServiceGrpc.newBlockingStub( SimpleServiceGrpc.SimpleServiceBlockingStub blockingStub = SimpleServiceGrpc.newBlockingStub(
channel); channel);
SimpleRequest request = SimpleRequest.newBuilder() SimpleRequest request = SimpleRequest.getDefaultInstance();
.build();
SimpleResponse goldenResponse = SimpleResponse.newBuilder() SimpleResponse goldenResponse = SimpleResponse.newBuilder()
.setResponseMessage("Hi, xDS! Authority= localhost:" + serverAddress.getPort()) .setResponseMessage("Hi, xDS! Authority= localhost:" + serverAddress.getPort())
.build(); .build();

View File

@ -413,7 +413,7 @@ public class XdsNameResolverTest {
Collections.singletonList(route1), Collections.singletonList(route1),
ImmutableMap.of()); ImmutableMap.of());
xdsClient.deliverRdsUpdate(RDS_RESOURCE_NAME, Collections.singletonList(virtualHost)); xdsClient.deliverRdsUpdate(RDS_RESOURCE_NAME, Collections.singletonList(virtualHost));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
assertServiceConfigForLoadBalancingConfig( assertServiceConfigForLoadBalancingConfig(
Collections.singletonList(cluster1), Collections.singletonList(cluster1),
(Map<String, ?>) resolutionResultCaptor.getValue().getServiceConfig().getConfig()); (Map<String, ?>) resolutionResultCaptor.getValue().getServiceConfig().getConfig());
@ -432,7 +432,7 @@ public class XdsNameResolverTest {
// Two new service config updates triggered: // Two new service config updates triggered:
// - with load balancing config being able to select cluster1 and cluster2 // - with load balancing config being able to select cluster1 and cluster2
// - with load balancing config being able to select cluster2 only // - with load balancing config being able to select cluster2 only
verify(mockListener, times(2)).onResult(resultCaptor.capture()); verify(mockListener, times(2)).onResult2(resultCaptor.capture());
assertServiceConfigForLoadBalancingConfig( assertServiceConfigForLoadBalancingConfig(
Arrays.asList(cluster1, cluster2), Arrays.asList(cluster1, cluster2),
(Map<String, ?>) resultCaptor.getAllValues().get(0).getServiceConfig().getConfig()); (Map<String, ?>) resultCaptor.getAllValues().get(0).getServiceConfig().getConfig());
@ -467,7 +467,7 @@ public class XdsNameResolverTest {
Collections.singletonList(route), Collections.singletonList(route),
ImmutableMap.of()); ImmutableMap.of());
xdsClient.deliverRdsUpdate(RDS_RESOURCE_NAME, Collections.singletonList(virtualHost)); xdsClient.deliverRdsUpdate(RDS_RESOURCE_NAME, Collections.singletonList(virtualHost));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
assertServiceConfigForLoadBalancingConfig( assertServiceConfigForLoadBalancingConfig(
Collections.singletonList(cluster1), Collections.singletonList(cluster1),
(Map<String, ?>) resolutionResultCaptor.getValue().getServiceConfig().getConfig()); (Map<String, ?>) resolutionResultCaptor.getValue().getServiceConfig().getConfig());
@ -483,7 +483,7 @@ public class XdsNameResolverTest {
verifyNoInteractions(mockListener); verifyNoInteractions(mockListener);
assertThat(xdsClient.rdsResource).isEqualTo(RDS_RESOURCE_NAME); assertThat(xdsClient.rdsResource).isEqualTo(RDS_RESOURCE_NAME);
xdsClient.deliverRdsUpdate(RDS_RESOURCE_NAME, Collections.singletonList(virtualHost)); xdsClient.deliverRdsUpdate(RDS_RESOURCE_NAME, Collections.singletonList(virtualHost));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
assertServiceConfigForLoadBalancingConfig( assertServiceConfigForLoadBalancingConfig(
Collections.singletonList(cluster1), Collections.singletonList(cluster1),
(Map<String, ?>) resolutionResultCaptor.getValue().getServiceConfig().getConfig()); (Map<String, ?>) resolutionResultCaptor.getValue().getServiceConfig().getConfig());
@ -506,7 +506,7 @@ public class XdsNameResolverTest {
Collections.singletonList(route), Collections.singletonList(route),
ImmutableMap.of()); ImmutableMap.of());
xdsClient.deliverRdsUpdate(RDS_RESOURCE_NAME, Collections.singletonList(virtualHost)); xdsClient.deliverRdsUpdate(RDS_RESOURCE_NAME, Collections.singletonList(virtualHost));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
assertServiceConfigForLoadBalancingConfig( assertServiceConfigForLoadBalancingConfig(
Collections.singletonList(cluster1), Collections.singletonList(cluster1),
(Map<String, ?>) resolutionResultCaptor.getValue().getServiceConfig().getConfig()); (Map<String, ?>) resolutionResultCaptor.getValue().getServiceConfig().getConfig());
@ -518,7 +518,7 @@ public class XdsNameResolverTest {
// Simulate management server adds back the previously used RDS resource. // Simulate management server adds back the previously used RDS resource.
reset(mockListener); reset(mockListener);
xdsClient.deliverRdsUpdate(RDS_RESOURCE_NAME, Collections.singletonList(virtualHost)); xdsClient.deliverRdsUpdate(RDS_RESOURCE_NAME, Collections.singletonList(virtualHost));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
assertServiceConfigForLoadBalancingConfig( assertServiceConfigForLoadBalancingConfig(
Collections.singletonList(cluster1), Collections.singletonList(cluster1),
(Map<String, ?>) resolutionResultCaptor.getValue().getServiceConfig().getConfig()); (Map<String, ?>) resolutionResultCaptor.getValue().getServiceConfig().getConfig());
@ -585,7 +585,7 @@ public class XdsNameResolverTest {
resolver.start(mockListener); resolver.start(mockListener);
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient(); FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
xdsClient.deliverLdsUpdate(0L, Arrays.asList(virtualHost)); xdsClient.deliverLdsUpdate(0L, Arrays.asList(virtualHost));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
assertServiceConfigForLoadBalancingConfig( assertServiceConfigForLoadBalancingConfig(
Collections.singletonList(cluster1), Collections.singletonList(cluster1),
(Map<String, ?>) resolutionResultCaptor.getValue().getServiceConfig().getConfig()); (Map<String, ?>) resolutionResultCaptor.getValue().getServiceConfig().getConfig());
@ -671,7 +671,7 @@ public class XdsNameResolverTest {
Collections.singletonList(AUTHORITY), Collections.singletonList(route), Collections.singletonList(AUTHORITY), Collections.singletonList(route),
ImmutableMap.of()); ImmutableMap.of());
xdsClient.deliverLdsUpdate(0L, Collections.singletonList(virtualHost)); xdsClient.deliverLdsUpdate(0L, Collections.singletonList(virtualHost));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY); InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
assertCallSelectClusterResult(call1, configSelector, cluster1, null); assertCallSelectClusterResult(call1, configSelector, cluster1, null);
@ -690,7 +690,7 @@ public class XdsNameResolverTest {
ImmutableMap.of()); ImmutableMap.of());
xdsClient.deliverLdsUpdate(TimeUnit.SECONDS.toNanos(5L), xdsClient.deliverLdsUpdate(TimeUnit.SECONDS.toNanos(5L),
Collections.singletonList(virtualHost)); Collections.singletonList(virtualHost));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY); InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
assertCallSelectClusterResult(call1, configSelector, cluster1, 5.0); assertCallSelectClusterResult(call1, configSelector, cluster1, 5.0);
@ -719,7 +719,7 @@ public class XdsNameResolverTest {
retryPolicy, retryPolicy,
false), false),
ImmutableMap.of()))); ImmutableMap.of())));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY); InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
Result selectResult = configSelector.selectConfig( Result selectResult = configSelector.selectConfig(
@ -777,7 +777,7 @@ public class XdsNameResolverTest {
RouteAction.forCluster(cluster2, Collections.emptyList(), RouteAction.forCluster(cluster2, Collections.emptyList(),
TimeUnit.SECONDS.toNanos(15L), null, false), TimeUnit.SECONDS.toNanos(15L), null, false),
ImmutableMap.of()))); ImmutableMap.of())));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
assertThat(result.getAddressesOrError().getValue()).isEmpty(); assertThat(result.getAddressesOrError().getValue()).isEmpty();
assertServiceConfigForLoadBalancingConfig( assertServiceConfigForLoadBalancingConfig(
@ -814,7 +814,7 @@ public class XdsNameResolverTest {
null, null,
false), false),
ImmutableMap.of()))); ImmutableMap.of())));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
InternalConfigSelector configSelector = InternalConfigSelector configSelector =
resolutionResultCaptor.getValue().getAttributes().get(InternalConfigSelector.KEY); resolutionResultCaptor.getValue().getAttributes().get(InternalConfigSelector.KEY);
@ -850,7 +850,7 @@ public class XdsNameResolverTest {
null, null,
false), false),
ImmutableMap.of()))); ImmutableMap.of())));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
InternalConfigSelector configSelector = InternalConfigSelector configSelector =
resolutionResultCaptor.getValue().getAttributes().get(InternalConfigSelector.KEY); resolutionResultCaptor.getValue().getAttributes().get(InternalConfigSelector.KEY);
@ -890,7 +890,7 @@ public class XdsNameResolverTest {
null, null,
false), false),
ImmutableMap.of()))); ImmutableMap.of())));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
InternalConfigSelector configSelector = InternalConfigSelector configSelector =
resolutionResultCaptor.getValue().getAttributes().get(InternalConfigSelector.KEY); resolutionResultCaptor.getValue().getAttributes().get(InternalConfigSelector.KEY);
@ -928,7 +928,7 @@ public class XdsNameResolverTest {
null, null,
false), false),
ImmutableMap.of()))); ImmutableMap.of())));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
configSelector = resolutionResultCaptor.getValue().getAttributes().get( configSelector = resolutionResultCaptor.getValue().getAttributes().get(
InternalConfigSelector.KEY); InternalConfigSelector.KEY);
@ -962,7 +962,7 @@ public class XdsNameResolverTest {
null, null,
true), true),
ImmutableMap.of()))); ImmutableMap.of())));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
InternalConfigSelector configSelector = InternalConfigSelector configSelector =
resolutionResultCaptor.getValue().getAttributes().get(InternalConfigSelector.KEY); resolutionResultCaptor.getValue().getAttributes().get(InternalConfigSelector.KEY);
@ -993,7 +993,7 @@ public class XdsNameResolverTest {
null, null,
false), false),
ImmutableMap.of()))); ImmutableMap.of())));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
InternalConfigSelector configSelector = InternalConfigSelector configSelector =
resolutionResultCaptor.getValue().getAttributes().get(InternalConfigSelector.KEY); resolutionResultCaptor.getValue().getAttributes().get(InternalConfigSelector.KEY);
@ -1027,7 +1027,7 @@ public class XdsNameResolverTest {
cluster2, Collections.emptyList(), TimeUnit.SECONDS.toNanos(15L), cluster2, Collections.emptyList(), TimeUnit.SECONDS.toNanos(15L),
null, false), null, false),
ImmutableMap.of()))); ImmutableMap.of())));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
// Updated service config still contains cluster1 while it is removed resource. New calls no // Updated service config still contains cluster1 while it is removed resource. New calls no
// longer routed to cluster1. // longer routed to cluster1.
@ -1039,7 +1039,7 @@ public class XdsNameResolverTest {
assertCallSelectClusterResult(call1, configSelector, "another-cluster", 20.0); assertCallSelectClusterResult(call1, configSelector, "another-cluster", 20.0);
firstCall.deliverErrorStatus(); // completes previous call firstCall.deliverErrorStatus(); // completes previous call
verify(mockListener, times(2)).onResult(resolutionResultCaptor.capture()); verify(mockListener, times(2)).onResult2(resolutionResultCaptor.capture());
result = resolutionResultCaptor.getValue(); result = resolutionResultCaptor.getValue();
assertServiceConfigForLoadBalancingConfig( assertServiceConfigForLoadBalancingConfig(
Arrays.asList(cluster2, "another-cluster"), Arrays.asList(cluster2, "another-cluster"),
@ -1069,7 +1069,7 @@ public class XdsNameResolverTest {
ImmutableMap.of()))); ImmutableMap.of())));
// Two consecutive service config updates: one for removing clcuster1, // Two consecutive service config updates: one for removing clcuster1,
// one for adding "another=cluster". // one for adding "another=cluster".
verify(mockListener, times(2)).onResult(resolutionResultCaptor.capture()); verify(mockListener, times(2)).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
assertServiceConfigForLoadBalancingConfig( assertServiceConfigForLoadBalancingConfig(
Arrays.asList(cluster2, "another-cluster"), Arrays.asList(cluster2, "another-cluster"),
@ -1104,7 +1104,7 @@ public class XdsNameResolverTest {
TimeUnit.SECONDS.toNanos(15L), null, false), TimeUnit.SECONDS.toNanos(15L), null, false),
ImmutableMap.of()))); ImmutableMap.of())));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
assertServiceConfigForLoadBalancingConfig( assertServiceConfigForLoadBalancingConfig(
Arrays.asList(cluster1, cluster2, "another-cluster"), Arrays.asList(cluster1, cluster2, "another-cluster"),
@ -1179,7 +1179,7 @@ public class XdsNameResolverTest {
TimeUnit.SECONDS.toNanos(20L), TimeUnit.SECONDS.toNanos(20L),
null, false), null, false),
ImmutableMap.of()))); ImmutableMap.of())));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
assertThat(result.getAddressesOrError().getValue()).isEmpty(); assertThat(result.getAddressesOrError().getValue()).isEmpty();
assertServiceConfigForLoadBalancingConfig( assertServiceConfigForLoadBalancingConfig(
@ -1208,7 +1208,7 @@ public class XdsNameResolverTest {
TimeUnit.SECONDS.toNanos(20L), TimeUnit.SECONDS.toNanos(20L),
null, false), null, false),
ImmutableMap.of()))); ImmutableMap.of())));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
assertThat(result.getAddressesOrError().getValue()).isEmpty(); assertThat(result.getAddressesOrError().getValue()).isEmpty();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -1256,7 +1256,7 @@ public class XdsNameResolverTest {
TimeUnit.SECONDS.toNanos(30L), TimeUnit.SECONDS.toNanos(30L),
null, false), null, false),
ImmutableMap.of()))); ImmutableMap.of())));
verify(mockListener, times(2)).onResult(resolutionResultCaptor.capture()); verify(mockListener, times(2)).onResult2(resolutionResultCaptor.capture());
ResolutionResult result2 = resolutionResultCaptor.getValue(); ResolutionResult result2 = resolutionResultCaptor.getValue();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, ?> resultServiceConfig2 = (Map<String, ?>) result2.getServiceConfig().getConfig(); Map<String, ?> resultServiceConfig2 = (Map<String, ?>) result2.getServiceConfig().getConfig();
@ -1599,7 +1599,7 @@ public class XdsNameResolverTest {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void assertEmptyResolutionResult(String resource) { private void assertEmptyResolutionResult(String resource) {
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
assertThat(result.getAddressesOrError().getValue()).isEmpty(); assertThat(result.getAddressesOrError().getValue()).isEmpty();
assertThat((Map<String, ?>) result.getServiceConfig().getConfig()).isEmpty(); assertThat((Map<String, ?>) result.getServiceConfig().getConfig()).isEmpty();
@ -1611,7 +1611,7 @@ public class XdsNameResolverTest {
} }
private void assertClusterResolutionResult(CallInfo call, String expectedCluster) { private void assertClusterResolutionResult(CallInfo call, String expectedCluster) {
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY); InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
assertCallSelectClusterResult(call, configSelector, expectedCluster, null); assertCallSelectClusterResult(call, configSelector, expectedCluster, null);
@ -1685,7 +1685,7 @@ public class XdsNameResolverTest {
cluster2, Collections.emptyList(), TimeUnit.SECONDS.toNanos(15L), cluster2, Collections.emptyList(), TimeUnit.SECONDS.toNanos(15L),
null, false), null, false),
ImmutableMap.of()))); ImmutableMap.of())));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
assertThat(result.getAddressesOrError().getValue()).isEmpty(); assertThat(result.getAddressesOrError().getValue()).isEmpty();
assertServiceConfigForLoadBalancingConfig( assertServiceConfigForLoadBalancingConfig(
@ -1763,7 +1763,7 @@ public class XdsNameResolverTest {
ImmutableMap.of()); ImmutableMap.of());
xdsClient.deliverRdsUpdate(RDS_RESOURCE_NAME, Collections.singletonList(virtualHost)); xdsClient.deliverRdsUpdate(RDS_RESOURCE_NAME, Collections.singletonList(virtualHost));
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
String expectedServiceConfigJson = String expectedServiceConfigJson =
"{\n" "{\n"
+ " \"loadBalancingConfig\": [{\n" + " \"loadBalancingConfig\": [{\n"
@ -1946,7 +1946,7 @@ public class XdsNameResolverTest {
FaultAbort.forHeader(FaultConfig.FractionalPercent.perHundred(70)), FaultAbort.forHeader(FaultConfig.FractionalPercent.perHundred(70)),
null); null);
xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null); xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY); InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
// no header abort key provided in metadata, rpc should succeed // no header abort key provided in metadata, rpc should succeed
@ -1985,7 +1985,7 @@ public class XdsNameResolverTest {
FaultAbort.forHeader(FaultConfig.FractionalPercent.perMillion(600_000)), FaultAbort.forHeader(FaultConfig.FractionalPercent.perMillion(600_000)),
null); null);
xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null); xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
result = resolutionResultCaptor.getValue(); result = resolutionResultCaptor.getValue();
configSelector = result.getAttributes().get(InternalConfigSelector.KEY); configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector, observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector,
@ -2001,7 +2001,7 @@ public class XdsNameResolverTest {
FaultAbort.forHeader(FaultConfig.FractionalPercent.perMillion(0)), FaultAbort.forHeader(FaultConfig.FractionalPercent.perMillion(0)),
null); null);
xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null); xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
result = resolutionResultCaptor.getValue(); result = resolutionResultCaptor.getValue();
configSelector = result.getAttributes().get(InternalConfigSelector.KEY); configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector, observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector,
@ -2016,7 +2016,7 @@ public class XdsNameResolverTest {
FaultConfig.FractionalPercent.perMillion(600_000)), FaultConfig.FractionalPercent.perMillion(600_000)),
null); null);
xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null); xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
result = resolutionResultCaptor.getValue(); result = resolutionResultCaptor.getValue();
configSelector = result.getAttributes().get(InternalConfigSelector.KEY); configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector, observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector,
@ -2034,7 +2034,7 @@ public class XdsNameResolverTest {
FaultConfig.FractionalPercent.perMillion(400_000)), FaultConfig.FractionalPercent.perMillion(400_000)),
null); null);
xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null); xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
result = resolutionResultCaptor.getValue(); result = resolutionResultCaptor.getValue();
configSelector = result.getAttributes().get(InternalConfigSelector.KEY); configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector, observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector,
@ -2052,7 +2052,7 @@ public class XdsNameResolverTest {
FaultConfig httpFilterFaultConfig = FaultConfig.create( FaultConfig httpFilterFaultConfig = FaultConfig.create(
FaultDelay.forHeader(FaultConfig.FractionalPercent.perHundred(70)), null, null); FaultDelay.forHeader(FaultConfig.FractionalPercent.perHundred(70)), null, null);
xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null); xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY); InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
// no header delay key provided in metadata, rpc should succeed immediately // no header delay key provided in metadata, rpc should succeed immediately
@ -2069,7 +2069,7 @@ public class XdsNameResolverTest {
httpFilterFaultConfig = FaultConfig.create( httpFilterFaultConfig = FaultConfig.create(
FaultDelay.forHeader(FaultConfig.FractionalPercent.perMillion(600_000)), null, null); FaultDelay.forHeader(FaultConfig.FractionalPercent.perMillion(600_000)), null, null);
xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null); xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
result = resolutionResultCaptor.getValue(); result = resolutionResultCaptor.getValue();
configSelector = result.getAttributes().get(InternalConfigSelector.KEY); configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector, observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector,
@ -2080,7 +2080,7 @@ public class XdsNameResolverTest {
httpFilterFaultConfig = FaultConfig.create( httpFilterFaultConfig = FaultConfig.create(
FaultDelay.forHeader(FaultConfig.FractionalPercent.perMillion(0)), null, null); FaultDelay.forHeader(FaultConfig.FractionalPercent.perMillion(0)), null, null);
xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null); xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
result = resolutionResultCaptor.getValue(); result = resolutionResultCaptor.getValue();
configSelector = result.getAttributes().get(InternalConfigSelector.KEY); configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector, observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector,
@ -2093,7 +2093,7 @@ public class XdsNameResolverTest {
null, null,
null); null);
xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null); xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
result = resolutionResultCaptor.getValue(); result = resolutionResultCaptor.getValue();
configSelector = result.getAttributes().get(InternalConfigSelector.KEY); configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector, observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector,
@ -2106,7 +2106,7 @@ public class XdsNameResolverTest {
null, null,
null); null);
xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null); xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
result = resolutionResultCaptor.getValue(); result = resolutionResultCaptor.getValue();
configSelector = result.getAttributes().get(InternalConfigSelector.KEY); configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector, observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector,
@ -2125,7 +2125,7 @@ public class XdsNameResolverTest {
null, null,
/* maxActiveFaults= */ 1); /* maxActiveFaults= */ 1);
xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null); xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY); InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
@ -2155,7 +2155,7 @@ public class XdsNameResolverTest {
null, null,
null); null);
xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null); xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY); InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
@ -2187,7 +2187,7 @@ public class XdsNameResolverTest {
FaultConfig.FractionalPercent.perMillion(1000_000)), FaultConfig.FractionalPercent.perMillion(1000_000)),
null); null);
xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null); xdsClient.deliverLdsUpdateWithFaultInjection(cluster1, httpFilterFaultConfig, null, null, null);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY); InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
ClientCall.Listener<Void> observer = startNewCall(TestMethodDescriptors.voidMethod(), ClientCall.Listener<Void> observer = startNewCall(TestMethodDescriptors.voidMethod(),
@ -2216,7 +2216,7 @@ public class XdsNameResolverTest {
null); null);
xdsClient.deliverLdsUpdateWithFaultInjection( xdsClient.deliverLdsUpdateWithFaultInjection(
cluster1, httpFilterFaultConfig, virtualHostFaultConfig, null, null); cluster1, httpFilterFaultConfig, virtualHostFaultConfig, null, null);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY); InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
ClientCall.Listener<Void> observer = startNewCall(TestMethodDescriptors.voidMethod(), ClientCall.Listener<Void> observer = startNewCall(TestMethodDescriptors.voidMethod(),
@ -2231,7 +2231,7 @@ public class XdsNameResolverTest {
null); null);
xdsClient.deliverLdsUpdateWithFaultInjection( xdsClient.deliverLdsUpdateWithFaultInjection(
cluster1, httpFilterFaultConfig, virtualHostFaultConfig, routeFaultConfig, null); cluster1, httpFilterFaultConfig, virtualHostFaultConfig, routeFaultConfig, null);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
result = resolutionResultCaptor.getValue(); result = resolutionResultCaptor.getValue();
configSelector = result.getAttributes().get(InternalConfigSelector.KEY); configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector, observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector,
@ -2248,7 +2248,7 @@ public class XdsNameResolverTest {
xdsClient.deliverLdsUpdateWithFaultInjection( xdsClient.deliverLdsUpdateWithFaultInjection(
cluster1, httpFilterFaultConfig, virtualHostFaultConfig, routeFaultConfig, cluster1, httpFilterFaultConfig, virtualHostFaultConfig, routeFaultConfig,
weightedClusterFaultConfig); weightedClusterFaultConfig);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
result = resolutionResultCaptor.getValue(); result = resolutionResultCaptor.getValue();
configSelector = result.getAttributes().get(InternalConfigSelector.KEY); configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector, observer = startNewCall(TestMethodDescriptors.voidMethod(), configSelector,
@ -2277,7 +2277,7 @@ public class XdsNameResolverTest {
FaultAbort.forStatus(Status.UNKNOWN, FaultConfig.FractionalPercent.perMillion(1000_000)), FaultAbort.forStatus(Status.UNKNOWN, FaultConfig.FractionalPercent.perMillion(1000_000)),
null); null);
xdsClient.deliverRdsUpdateWithFaultInjection(RDS_RESOURCE_NAME, null, routeFaultConfig, null); xdsClient.deliverRdsUpdateWithFaultInjection(RDS_RESOURCE_NAME, null, routeFaultConfig, null);
verify(mockListener).onResult(resolutionResultCaptor.capture()); verify(mockListener).onResult2(resolutionResultCaptor.capture());
ResolutionResult result = resolutionResultCaptor.getValue(); ResolutionResult result = resolutionResultCaptor.getValue();
InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY); InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
ClientCall.Listener<Void> observer = startNewCall(TestMethodDescriptors.voidMethod(), ClientCall.Listener<Void> observer = startNewCall(TestMethodDescriptors.voidMethod(),