Skip to content

Commit 7d4a961

Browse files
committed
xds: Update and add tests for proactive connection
Update existing unit tests and add new test cases to validate the proactive connection behavior. Verification counts in several tests have been adjusted to reflect that the balancer now initiates connections immediately upon subchannel failure.
1 parent 1291582 commit 7d4a961

File tree

1 file changed

+47
-15
lines changed

1 file changed

+47
-15
lines changed

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

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ public void aggregateSubchannelStates_connectingReadyIdleFailure() {
255255
inOrder.verify(helper).refreshNameResolution();
256256
inOrder.verify(helper).updateBalancingState(eq(CONNECTING), any());
257257
}
258-
verifyConnection(0);
258+
verifyConnection(1);
259259
}
260260

261261
private void verifyConnection(int times) {
@@ -537,7 +537,7 @@ public void pickWithRandomHash_firstSubchannelInTransientFailure_remainingSubcha
537537
// Bring one subchannel to TRANSIENT_FAILURE.
538538
deliverSubchannelUnreachable(getSubChannel(servers.get(0)));
539539
verify(helper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
540-
verifyConnection(0);
540+
verifyConnection(1);
541541

542542
// Pick subchannel with random hash does trigger connection by walking the ring
543543
// and choosing the first (at most one) IDLE subchannel along the way.
@@ -583,7 +583,7 @@ public void skipFailingHosts_pickNextNonFailingHost() {
583583
getSubChannel(servers.get(0)),
584584
ConnectivityStateInfo.forTransientFailure(
585585
Status.UNAVAILABLE.withDescription("unreachable")));
586-
verify(helper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
586+
verify(helper, atLeastOnce()).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
587587

588588
PickResult result = pickerCaptor.getValue().pickSubchannel(args);
589589
assertThat(result.getStatus().isOk()).isTrue();
@@ -649,7 +649,7 @@ public void skipFailingHosts_firstTwoHostsFailed_pickNextFirstReady() {
649649
ConnectivityStateInfo.forTransientFailure(
650650
Status.PERMISSION_DENIED.withDescription("permission denied")));
651651
verify(helper).updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture());
652-
verifyConnection(0);
652+
verifyConnection(2);
653653
PickResult result = pickerCaptor.getValue().pickSubchannel(args); // activate last subchannel
654654
assertThat(result.getStatus().isOk()).isTrue();
655655
int expectedCount = PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? 0 : 1;
@@ -721,7 +721,7 @@ public void allSubchannelsInTransientFailure() {
721721
}
722722
verify(helper, atLeastOnce())
723723
.updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture());
724-
verifyConnection(0);
724+
verifyConnection(2);
725725

726726
// Picking subchannel triggers connection. RPC hash hits server0.
727727
PickSubchannelArgs args = getDefaultPickSubchannelArgsForServer(0);
@@ -740,12 +740,13 @@ public void firstSubchannelIdle() {
740740
List<EquivalentAddressGroup> servers = createWeightedServerAddrs(1, 1, 1);
741741
initializeLbSubchannels(config, servers);
742742

743-
// Go to TF does nothing, though PF will try to reconnect after backoff
743+
// As per gRFC A61, entering TF triggers a proactive connection attempt
744+
// on an IDLE subchannel because no other subchannel is currently CONNECTING.
744745
deliverSubchannelState(getSubchannel(servers, 1),
745746
ConnectivityStateInfo.forTransientFailure(
746747
Status.UNAVAILABLE.withDescription("unreachable")));
747748
verify(helper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
748-
verifyConnection(0);
749+
verifyConnection(1);
749750

750751
// Picking subchannel triggers connection. RPC hash hits server0.
751752
PickSubchannelArgs args = getDefaultPickSubchannelArgs(hashFunc.hashVoid());
@@ -796,7 +797,7 @@ public void firstSubchannelFailure() {
796797
ConnectivityStateInfo.forTransientFailure(
797798
Status.UNAVAILABLE.withDescription("unreachable")));
798799
verify(helper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
799-
verifyConnection(0);
800+
verifyConnection(1);
800801

801802
// Per GRFC A61 Picking subchannel should no longer request connections that were failing
802803
PickSubchannelArgs args = getDefaultPickSubchannelArgs(hashFunc.hashVoid());
@@ -805,8 +806,6 @@ public void firstSubchannelFailure() {
805806
assertThat(result.getStatus().isOk()).isTrue();
806807
assertThat(result.getSubchannel()).isNull();
807808
verify(subchannelList.get(0), never()).requestConnection(); // In TF
808-
verify(subchannelList.get(1)).requestConnection();
809-
verify(subchannelList.get(2), never()).requestConnection(); // Not one of the first 2
810809
}
811810

812811
@Test
@@ -824,7 +823,7 @@ public void secondSubchannelConnecting() {
824823

825824
Subchannel firstSubchannel = getSubchannel(servers, 0);
826825
deliverSubchannelUnreachable(firstSubchannel);
827-
verifyConnection(0);
826+
verifyConnection(1);
828827

829828
deliverSubchannelState(getSubchannel(servers, 2), CSI_CONNECTING);
830829
verify(helper, times(2)).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
@@ -833,7 +832,7 @@ public void secondSubchannelConnecting() {
833832
// Picking subchannel when idle triggers connection.
834833
deliverSubchannelState(getSubchannel(servers, 2),
835834
ConnectivityStateInfo.forNonError(IDLE));
836-
verifyConnection(0);
835+
verifyConnection(1);
837836
PickSubchannelArgs args = getDefaultPickSubchannelArgs(hashFunc.hashVoid());
838837
PickResult result = pickerCaptor.getValue().pickSubchannel(args);
839838
assertThat(result.getStatus().isOk()).isTrue();
@@ -857,7 +856,7 @@ public void secondSubchannelFailure() {
857856
deliverSubchannelUnreachable(firstSubchannel);
858857
deliverSubchannelUnreachable(getSubchannel(servers, 2));
859858
verify(helper).updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture());
860-
verifyConnection(0);
859+
verifyConnection(2);
861860

862861
// Picking subchannel triggers connection.
863862
PickSubchannelArgs args = getDefaultPickSubchannelArgs(hashFunc.hashVoid());
@@ -887,7 +886,7 @@ public void thirdSubchannelConnecting() {
887886
deliverSubchannelState(getSubchannel(servers, 1), CSI_CONNECTING);
888887
verify(helper, atLeastOnce())
889888
.updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture());
890-
verifyConnection(0);
889+
verifyConnection(2);
891890

892891
// Picking subchannel should not trigger connection per gRFC A61.
893892
PickSubchannelArgs args = getDefaultPickSubchannelArgs(hashFunc.hashVoid());
@@ -909,7 +908,7 @@ public void stickyTransientFailure() {
909908
deliverSubchannelUnreachable(firstSubchannel);
910909

911910
verify(helper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
912-
verifyConnection(0);
911+
verifyConnection(1);
913912

914913
reset(helper);
915914
deliverSubchannelState(firstSubchannel, ConnectivityStateInfo.forNonError(IDLE));
@@ -1127,6 +1126,39 @@ public void config_equalsTester() {
11271126
.testEquals();
11281127
}
11291128

1129+
@Test
1130+
public void tfWithoutConnectingChild_triggersIdleChildConnection() {
1131+
RingHashConfig config = new RingHashConfig(10, 100, "");
1132+
List<EquivalentAddressGroup> servers = createWeightedServerAddrs(1, 1);
1133+
1134+
initializeLbSubchannels(config, servers);
1135+
1136+
Subchannel tfSubchannel = getSubchannel(servers, 0);
1137+
Subchannel idleSubchannel = getSubchannel(servers, 1);
1138+
1139+
deliverSubchannelUnreachable(tfSubchannel);
1140+
1141+
Subchannel requested = connectionRequestedQueue.poll();
1142+
assertThat(requested).isSameInstanceAs(idleSubchannel);
1143+
assertThat(connectionRequestedQueue.poll()).isNull();
1144+
}
1145+
1146+
@Test
1147+
public void tfWithReadyChild_doesNotTriggerIdleChildConnection() {
1148+
RingHashConfig config = new RingHashConfig(10, 100, "");
1149+
List<EquivalentAddressGroup> servers = createWeightedServerAddrs(1, 1, 1);
1150+
1151+
initializeLbSubchannels(config, servers);
1152+
1153+
Subchannel tfSubchannel = getSubchannel(servers, 0);
1154+
Subchannel readySubchannel = getSubchannel(servers, 1);
1155+
1156+
deliverSubchannelState(readySubchannel, ConnectivityStateInfo.forNonError(READY));
1157+
deliverSubchannelUnreachable(tfSubchannel);
1158+
1159+
assertThat(connectionRequestedQueue.poll()).isNull();
1160+
}
1161+
11301162
private List<Subchannel> initializeLbSubchannels(RingHashConfig config,
11311163
List<EquivalentAddressGroup> servers, InitializationFlags... initFlags) {
11321164

0 commit comments

Comments
 (0)