xds: XdsClient should unsubscribe on last resource (#11264) · grpc/grpc-java@448ec4f
@@ -133,6 +133,7 @@
133133import org.mockito.junit.MockitoJUnit;
134134import org.mockito.junit.MockitoRule;
135135import org.mockito.stubbing.Answer;
136+import org.mockito.verification.VerificationMode;
136137137138/**
138139 * Tests for {@link XdsClientImpl}.
@@ -2757,6 +2758,37 @@ public void edsResourceNotFound() {
27572758verifySubscribedResourcesMetadataSizes(0, 0, 0, 1);
27582759 }
275927602761+@Test
2762+public void edsCleanupNonceAfterUnsubscription() {
2763+Assume.assumeFalse(ignoreResourceDeletion());
2764+2765+// Suppose we have an EDS subscription A.1
2766+xdsClient.watchXdsResource(XdsEndpointResource.getInstance(), "A.1", edsResourceWatcher);
2767+DiscoveryRpcCall call = resourceDiscoveryCalls.poll();
2768+assertThat(call).isNotNull();
2769+call.verifyRequest(EDS, "A.1", "", "", NODE);
2770+2771+// EDS -> {A.1}, version 1
2772+List<Message> dropOverloads = ImmutableList.of();
2773+List<Message> endpointsV1 = ImmutableList.of(lbEndpointHealthy);
2774+ImmutableMap<String, Any> resourcesV1 = ImmutableMap.of(
2775+"A.1", Any.pack(mf.buildClusterLoadAssignment("A.1", endpointsV1, dropOverloads)));
2776+call.sendResponse(EDS, resourcesV1.values().asList(), VERSION_1, "0000");
2777+// {A.1} -> ACK, version 1
2778+call.verifyRequest(EDS, "A.1", VERSION_1, "0000", NODE);
2779+verify(edsResourceWatcher, times(1)).onChanged(any());
2780+2781+// trigger an EDS resource unsubscription.
2782+xdsClient.cancelXdsResourceWatch(XdsEndpointResource.getInstance(), "A.1", edsResourceWatcher);
2783+verifySubscribedResourcesMetadataSizes(0, 0, 0, 0);
2784+call.verifyRequest(EDS, Arrays.asList(), VERSION_1, "0000", NODE);
2785+2786+// When re-subscribing, the version and nonce were properly forgotten, so the request is the
2787+// same as the initial request
2788+xdsClient.watchXdsResource(XdsEndpointResource.getInstance(), "A.1", edsResourceWatcher);
2789+call.verifyRequest(EDS, "A.1", "", "", NODE, Mockito.timeout(2000).times(2));
2790+ }
2791+27602792@Test
27612793public void edsResponseErrorHandling_allResourcesFailedUnpack() {
27622794DiscoveryRpcCall call = startResourceWatcher(XdsEndpointResource.getInstance(), EDS_RESOURCE,
@@ -3787,10 +3819,22 @@ protected abstract static class DiscoveryRpcCall {
3787381937883820protected void verifyRequest(
37893821XdsResourceType<?> type, List<String> resources, String versionInfo, String nonce,
3790-Node node) {
3822+Node node, VerificationMode verificationMode) {
37913823throw new UnsupportedOperationException();
37923824 }
379338253826+protected void verifyRequest(
3827+XdsResourceType<?> type, List<String> resources, String versionInfo, String nonce,
3828+Node node) {
3829+verifyRequest(type, resources, versionInfo, nonce, node, Mockito.timeout(2000));
3830+ }
3831+3832+protected void verifyRequest(
3833+XdsResourceType<?> type, String resource, String versionInfo, String nonce,
3834+Node node, VerificationMode verificationMode) {
3835+verifyRequest(type, ImmutableList.of(resource), versionInfo, nonce, node, verificationMode);
3836+ }
3837+37943838protected void verifyRequest(
37953839XdsResourceType<?> type, String resource, String versionInfo, String nonce, Node node) {
37963840verifyRequest(type, ImmutableList.of(resource), versionInfo, nonce, node);