Skip to content

Commit 38f1da0

Browse files
committed
ldsResponse_errorUnpackListeners_single WIP
1 parent db20bf5 commit 38f1da0

File tree

4 files changed

+89
-8
lines changed

4 files changed

+89
-8
lines changed

xds/src/main/java/io/grpc/xds/ClientXdsClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ final class ClientXdsClient extends AbstractXdsClient {
102102
static final String HASH_POLICY_FILTER_STATE_KEY = "io.grpc.channel_id";
103103
@VisibleForTesting
104104
static boolean enableFaultInjection =
105-
Boolean.parseBoolean(System.getenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"));
105+
Boolean.parseBoolean(System.getenv("GRPC_ZXDS_EXPERIMENTAL_FAULT_INJECTION"));
106106

107107
private static final String TYPE_URL_HTTP_CONNECTION_MANAGER_V2 =
108108
"type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2"

xds/src/test/java/io/grpc/xds/ClientXdsClientTestBase.java

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import com.google.common.collect.ImmutableMap;
3434
import com.google.common.collect.Iterables;
3535
import com.google.protobuf.Any;
36+
import com.google.protobuf.InvalidProtocolBufferException;
3637
import com.google.protobuf.Message;
3738
import com.google.protobuf.StringValue;
3839
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.SdsSecretConfig;
@@ -104,6 +105,8 @@ public abstract class ClientXdsClientTestBase {
104105
private static final String VERSION_1 = "42";
105106
private static final String VERSION_2 = "43";
106107
private static final Node NODE = Node.newBuilder().build();
108+
/** Throws {@link InvalidProtocolBufferException} on {@link Any#unpack(Class)}. */
109+
static final Any FAILING_ANY = Any.newBuilder().setTypeUrl("fake").build();
107110

108111
private static final FakeClock.TaskFilter RPC_RETRY_TASK_FILTER =
109112
new FakeClock.TaskFilter() {
@@ -226,12 +229,15 @@ public long currentTimeNanos() {
226229

227230
@Before
228231
public void setUp() throws IOException {
229-
originalEnableFaultInjection = ClientXdsClient.enableFaultInjection;
230-
ClientXdsClient.enableFaultInjection = true;
232+
// Init mocks.
231233
MockitoAnnotations.initMocks(this);
232234
when(backoffPolicyProvider.get()).thenReturn(backoffPolicy1, backoffPolicy2);
233235
when(backoffPolicy1.nextBackoffNanos()).thenReturn(10L, 100L);
234236
when(backoffPolicy2.nextBackoffNanos()).thenReturn(20L, 200L);
237+
238+
// Start the server and the client.
239+
originalEnableFaultInjection = ClientXdsClient.enableFaultInjection;
240+
ClientXdsClient.enableFaultInjection = true;
235241
final String serverName = InProcessServerBuilder.generateName();
236242
cleanupRule.register(
237243
InProcessServerBuilder
@@ -342,6 +348,17 @@ public void ldsResourceNotFound() {
342348
verifySubscribedResourcesMetadataSizes(1, 0, 0, 0);
343349
}
344350

351+
@Test
352+
public void ldsResponse_errorUnpackListeners_metadataRequested() {
353+
DiscoveryRpcCall call = startResourceWatcher(LDS, LDS_RESOURCE, ldsResourceWatcher);
354+
355+
// Client sends an NACK LDS request.
356+
call.sendResponse(LDS, FAILING_ANY, VERSION_1, "0000");
357+
call.verifyRequestNack(LDS, LDS_RESOURCE, "", "0000", NODE, "^Malformed LDS response.*");
358+
verifyNoInteractions(ldsResourceWatcher);
359+
verifyResourceMetadataRequested(LDS, LDS_RESOURCE);
360+
}
361+
345362
@Test
346363
public void ldsResourceFound_containsVirtualHosts() {
347364
DiscoveryRpcCall call = startResourceWatcher(LDS, LDS_RESOURCE, ldsResourceWatcher);
@@ -1512,6 +1529,17 @@ protected void verifyRequest(
15121529
verifyRequest(type, ImmutableList.of(resource), versionInfo, nonce, node);
15131530
}
15141531

1532+
protected abstract void verifyRequestNack(
1533+
ResourceType type, List<String> resources, String versionInfo, String nonce, Node node,
1534+
@Nullable String errorMessageRegex);
1535+
1536+
protected void verifyRequestNack(
1537+
ResourceType type, String resource, String versionInfo, String nonce, Node node,
1538+
@Nullable String errorMessageRegex) {
1539+
verifyRequestNack(type, ImmutableList.of(resource), versionInfo, nonce, node,
1540+
errorMessageRegex);
1541+
}
1542+
15151543
protected abstract void verifyNoMoreRequest();
15161544

15171545
protected abstract void sendResponse(

xds/src/test/java/io/grpc/xds/ClientXdsClientV2Test.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.google.protobuf.UInt32Value;
3030
import com.google.protobuf.UInt64Value;
3131
import com.google.protobuf.util.Durations;
32+
import com.google.rpc.Code;
3233
import io.envoyproxy.envoy.api.v2.Cluster;
3334
import io.envoyproxy.envoy.api.v2.Cluster.CustomClusterType;
3435
import io.envoyproxy.envoy.api.v2.Cluster.DiscoveryType;
@@ -93,6 +94,7 @@
9394
import java.util.List;
9495
import java.util.Map;
9596
import java.util.Set;
97+
import java.util.regex.Pattern;
9698
import javax.annotation.Nullable;
9799
import org.junit.runner.RunWith;
98100
import org.junit.runners.JUnit4;
@@ -178,7 +180,16 @@ protected void verifyRequest(
178180
ResourceType type, List<String> resources, String versionInfo, String nonce,
179181
EnvoyProtoData.Node node) {
180182
verify(requestObserver).onNext(argThat(new DiscoveryRequestMatcher(
181-
node.toEnvoyProtoNodeV2(), versionInfo, resources, type.typeUrlV2(), nonce)));
183+
node.toEnvoyProtoNodeV2(), versionInfo, resources, type.typeUrlV2(), nonce, null, null)));
184+
}
185+
186+
@Override
187+
protected void verifyRequestNack(
188+
ResourceType type, List<String> resources, String versionInfo, String nonce,
189+
EnvoyProtoData.Node node, @Nullable String errorMessageRegex) {
190+
verify(requestObserver).onNext(argThat(new DiscoveryRequestMatcher(
191+
node.toEnvoyProtoNodeV2(), versionInfo, resources, type.typeUrlV2(), nonce,
192+
Code.INVALID_ARGUMENT_VALUE, errorMessageRegex)));
182193
}
183194

184195
@Override
@@ -563,14 +574,19 @@ private static class DiscoveryRequestMatcher implements ArgumentMatcher<Discover
563574
private final String typeUrl;
564575
private final Set<String> resources;
565576
private final String responseNonce;
577+
@Nullable private final Integer errorCode;
578+
@Nullable private final Pattern errorMessagePattern;
566579

567580
private DiscoveryRequestMatcher(Node node, String versionInfo, List<String> resources,
568-
String typeUrl, String responseNonce) {
581+
String typeUrl, String responseNonce, @Nullable Integer errorCode,
582+
@Nullable String errorMessageRegex) {
569583
this.node = node;
570584
this.versionInfo = versionInfo;
571585
this.resources = new HashSet<>(resources);
572586
this.typeUrl = typeUrl;
573587
this.responseNonce = responseNonce;
588+
this.errorCode = errorCode;
589+
errorMessagePattern = (errorMessageRegex != null) ? Pattern.compile(errorMessageRegex) : null;
574590
}
575591

576592
@Override
@@ -587,6 +603,16 @@ public boolean matches(DiscoveryRequest argument) {
587603
if (!resources.equals(new HashSet<>(argument.getResourceNamesList()))) {
588604
return false;
589605
}
606+
if (errorCode != null) {
607+
if (!argument.hasErrorDetail()) {
608+
return false;
609+
}
610+
com.google.rpc.Status errorDetail = argument.getErrorDetail();
611+
if (!errorCode.equals(errorDetail.getCode()) || (errorMessagePattern != null
612+
&& !errorMessagePattern.matcher(errorDetail.getMessage()).matches())) {
613+
return false;
614+
}
615+
}
590616
return node.equals(argument.getNode());
591617
}
592618
}

xds/src/test/java/io/grpc/xds/ClientXdsClientV3Test.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.google.protobuf.UInt32Value;
3030
import com.google.protobuf.UInt64Value;
3131
import com.google.protobuf.util.Durations;
32+
import com.google.rpc.Code;
3233
import io.envoyproxy.envoy.config.cluster.v3.CircuitBreakers;
3334
import io.envoyproxy.envoy.config.cluster.v3.CircuitBreakers.Thresholds;
3435
import io.envoyproxy.envoy.config.cluster.v3.Cluster;
@@ -98,6 +99,7 @@
9899
import java.util.List;
99100
import java.util.Map;
100101
import java.util.Set;
102+
import java.util.regex.Pattern;
101103
import javax.annotation.Nullable;
102104
import org.junit.runner.RunWith;
103105
import org.junit.runners.JUnit4;
@@ -183,7 +185,16 @@ protected void verifyRequest(
183185
ResourceType type, List<String> resources, String versionInfo, String nonce,
184186
EnvoyProtoData.Node node) {
185187
verify(requestObserver).onNext(argThat(new DiscoveryRequestMatcher(
186-
node.toEnvoyProtoNode(), versionInfo, resources, type.typeUrl(), nonce)));
188+
node.toEnvoyProtoNode(), versionInfo, resources, type.typeUrl(), nonce, null, null)));
189+
}
190+
191+
@Override
192+
protected void verifyRequestNack(
193+
ResourceType type, List<String> resources, String versionInfo, String nonce,
194+
EnvoyProtoData.Node node, @Nullable String errorMessageRegex) {
195+
verify(requestObserver).onNext(argThat(new DiscoveryRequestMatcher(
196+
node.toEnvoyProtoNode(), versionInfo, resources, type.typeUrl(), nonce,
197+
Code.INVALID_ARGUMENT_VALUE, errorMessageRegex)));
187198
}
188199

189200
@Override
@@ -603,14 +614,20 @@ private static class DiscoveryRequestMatcher implements ArgumentMatcher<Discover
603614
private final String typeUrl;
604615
private final Set<String> resources;
605616
private final String responseNonce;
617+
@Nullable private final Integer errorCode;
618+
@Nullable private final Pattern errorMessagePattern;
606619

607-
private DiscoveryRequestMatcher(Node node, String versionInfo, List<String> resources,
608-
String typeUrl, String responseNonce) {
620+
private DiscoveryRequestMatcher(
621+
Node node, String versionInfo, List<String> resources,
622+
String typeUrl, String responseNonce, @Nullable Integer errorCode,
623+
@Nullable String errorMessageRegex) {
609624
this.node = node;
610625
this.versionInfo = versionInfo;
611626
this.resources = new HashSet<>(resources);
612627
this.typeUrl = typeUrl;
613628
this.responseNonce = responseNonce;
629+
this.errorCode = errorCode;
630+
errorMessagePattern = (errorMessageRegex != null) ? Pattern.compile(errorMessageRegex) : null;
614631
}
615632

616633
@Override
@@ -627,6 +644,16 @@ public boolean matches(DiscoveryRequest argument) {
627644
if (!resources.equals(new HashSet<>(argument.getResourceNamesList()))) {
628645
return false;
629646
}
647+
if (errorCode != null) {
648+
if (!argument.hasErrorDetail()) {
649+
return false;
650+
}
651+
com.google.rpc.Status errorDetail = argument.getErrorDetail();
652+
if (!errorCode.equals(errorDetail.getCode()) || (errorMessagePattern != null
653+
&& !errorMessagePattern.matcher(errorDetail.getMessage()).matches())) {
654+
return false;
655+
}
656+
}
630657
return node.equals(argument.getNode());
631658
}
632659
}

0 commit comments

Comments
 (0)