diff --git a/grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancerTest.java b/grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancerTest.java index ef31b318cb5..fab813711c2 100644 --- a/grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancerTest.java +++ b/grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancerTest.java @@ -82,6 +82,7 @@ import io.grpc.inprocess.InProcessServerBuilder; import io.grpc.internal.BackoffPolicy; import io.grpc.internal.FakeClock; +import io.grpc.internal.PickFirstLoadBalancerProvider; import io.grpc.lb.v1.ClientStats; import io.grpc.lb.v1.ClientStatsPerToken; import io.grpc.lb.v1.FallbackResponse; @@ -1921,10 +1922,16 @@ public void grpclbWorking_pickFirstMode() throws Exception { // With delegation, the child pick_first creates the subchannel inOrder.verify(helper).createSubchannel(createSubchannelArgsCaptor.capture()); CreateSubchannelArgs createSubchannelArgs = createSubchannelArgsCaptor.getValue(); - assertThat(createSubchannelArgs.getAddresses()) - .containsExactly( - new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001")), - new EquivalentAddressGroup(backends1.get(1).addr, eagAttrsWithToken("token0002"))); + if (PickFirstLoadBalancerProvider.isEnabledNewPickFirst()) { + assertThat(createSubchannelArgs.getAddresses()) + .containsExactly( + new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001"))); + } else { + assertThat(createSubchannelArgs.getAddresses()) + .containsExactly( + new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001")), + new EquivalentAddressGroup(backends1.get(1).addr, eagAttrsWithToken("token0002"))); + } // Child pick_first eagerly connects, so we start in CONNECTING inOrder.verify(helper, atLeast(1)).updateBalancingState(eq(CONNECTING), pickerCaptor.capture()); @@ -1939,18 +1946,20 @@ public void grpclbWorking_pickFirstMode() throws Exception { // Child pick_first eagerly calls requestConnection() verify(subchannel).requestConnection(); - // TRANSIENT_FAILURE - Status error = Status.UNAVAILABLE.withDescription("Simulated connection error"); - deliverSubchannelState(subchannel, ConnectivityStateInfo.forTransientFailure(error)); - // The child LB will notify our helper, which updates grpclb state - inOrder.verify(helper, atLeast(1)) - .updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture()); - RoundRobinPicker picker1 = (RoundRobinPicker) pickerCaptor.getValue(); - assertThat(picker1.dropList).containsExactly(null, null); - ChildLbPickerEntry failureEntry = (ChildLbPickerEntry) picker1.pickList.get(0); - PickResult failureResult = - failureEntry.getChildPicker().pickSubchannel(mock(PickSubchannelArgs.class)); - assertThat(failureResult.getStatus()).isEqualTo(error); + if (!PickFirstLoadBalancerProvider.isEnabledNewPickFirst()) { + // TRANSIENT_FAILURE + Status error = Status.UNAVAILABLE.withDescription("Simulated connection error"); + deliverSubchannelState(subchannel, ConnectivityStateInfo.forTransientFailure(error)); + // The child LB will notify our helper, which updates grpclb state + inOrder.verify(helper, atLeast(1)) + .updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture()); + RoundRobinPicker picker1 = (RoundRobinPicker) pickerCaptor.getValue(); + assertThat(picker1.dropList).containsExactly(null, null); + ChildLbPickerEntry failureEntry = (ChildLbPickerEntry) picker1.pickList.get(0); + PickResult failureResult = + failureEntry.getChildPicker().pickSubchannel(mock(PickSubchannelArgs.class)); + assertThat(failureResult.getStatus()).isEqualTo(error); + } // READY deliverSubchannelState(subchannel, ConnectivityStateInfo.forNonError(READY)); @@ -1977,11 +1986,15 @@ public void grpclbWorking_pickFirstMode() throws Exception { assertThat(mockSubchannels).isEmpty(); // The child LB policy internally calls updateAddresses on the subchannel - verify(subchannel).updateAddresses( - eq(Arrays.asList( - new EquivalentAddressGroup(backends2.get(0).addr, eagAttrsWithToken("token0001")), - new EquivalentAddressGroup(backends2.get(2).addr, - eagAttrsWithToken("token0004"))))); + List expectedAddresses = + PickFirstLoadBalancerProvider.isEnabledNewPickFirst() + ? Collections.singletonList( + new EquivalentAddressGroup(backends2.get(0).addr, eagAttrsWithToken("token0001"))) + : Arrays.asList( + new EquivalentAddressGroup(backends2.get(0).addr, eagAttrsWithToken("token0001")), + new EquivalentAddressGroup(backends2.get(2).addr, + eagAttrsWithToken("token0004"))); + verify(subchannel).updateAddresses(eq(expectedAddresses)); inOrder.verify(helper, atLeast(1)).updateBalancingState(eq(READY), pickerCaptor.capture()); RoundRobinPicker picker3 = (RoundRobinPicker) pickerCaptor.getValue(); assertThat(picker3.dropList).containsExactly( @@ -2004,7 +2017,8 @@ public void grpclbWorking_pickFirstMode() throws Exception { assertThat(pick.getSubchannel()).isNull(); verify(subchannel, times(2)).requestConnection(); balancer.requestConnection(); - verify(subchannel, times(3)).requestConnection(); + int expectedRequests = PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? 2 : 3; + verify(subchannel, times(expectedRequests)).requestConnection(); // PICK_FIRST doesn't use subchannelPool verify(subchannelPool, never()) @@ -2045,10 +2059,16 @@ public void grpclbWorking_pickFirstMode_lbSendsEmptyAddress() throws Exception { // The child pick_first creates the first subchannel inOrder.verify(helper).createSubchannel(createSubchannelArgsCaptor.capture()); CreateSubchannelArgs createSubchannelArgs = createSubchannelArgsCaptor.getValue(); - assertThat(createSubchannelArgs.getAddresses()) - .containsExactly( - new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001")), - new EquivalentAddressGroup(backends1.get(1).addr, eagAttrsWithToken("token0002"))); + if (PickFirstLoadBalancerProvider.isEnabledNewPickFirst()) { + assertThat(createSubchannelArgs.getAddresses()) + .containsExactly( + new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001"))); + } else { + assertThat(createSubchannelArgs.getAddresses()) + .containsExactly( + new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001")), + new EquivalentAddressGroup(backends1.get(1).addr, eagAttrsWithToken("token0002"))); + } // Child pick_first eagerly connects, so initial state is CONNECTING inOrder.verify(helper, atLeast(1)).updateBalancingState(eq(CONNECTING), pickerCaptor.capture()); @@ -2104,7 +2124,18 @@ public void grpclbWorking_pickFirstMode_lbSendsEmptyAddress() throws Exception { lbResponseObserver.onNext(buildLbResponse(backends2)); // A NEW child LB and NEW subchannel are created upon recovery - inOrder.verify(helper).createSubchannel(any(CreateSubchannelArgs.class)); + inOrder.verify(helper).createSubchannel(createSubchannelArgsCaptor.capture()); + CreateSubchannelArgs createSubchannelArgs2 = createSubchannelArgsCaptor.getValue(); + if (PickFirstLoadBalancerProvider.isEnabledNewPickFirst()) { + assertThat(createSubchannelArgs2.getAddresses()) + .containsExactly( + new EquivalentAddressGroup(backends2.get(0).addr, eagAttrsWithToken("token0001"))); + } else { + assertThat(createSubchannelArgs2.getAddresses()) + .containsExactly( + new EquivalentAddressGroup(backends2.get(0).addr, eagAttrsWithToken("token0001")), + new EquivalentAddressGroup(backends2.get(2).addr, eagAttrsWithToken("token0004"))); + } assertThat(mockSubchannels).hasSize(1); Subchannel subchannel2 = mockSubchannels.poll(); inOrder.verify(helper, atLeast(1)).updateBalancingState(eq(CONNECTING), pickerCaptor.capture()); @@ -2180,8 +2211,13 @@ private void pickFirstModeFallback(long timeout) throws Exception { // Entering fallback mode - child LB is created for fallback backends inOrder.verify(helper).createSubchannel(createSubchannelArgsCaptor.capture()); CreateSubchannelArgs createSubchannelArgs = createSubchannelArgsCaptor.getValue(); - assertThat(createSubchannelArgs.getAddresses()) - .containsExactly(backendList.get(0), backendList.get(1)); + if (PickFirstLoadBalancerProvider.isEnabledNewPickFirst()) { + assertThat(createSubchannelArgs.getAddresses()) + .containsExactly(backendList.get(0)); + } else { + assertThat(createSubchannelArgs.getAddresses()) + .containsExactly(backendList.get(0), backendList.get(1)); + } assertThat(mockSubchannels).hasSize(1); Subchannel subchannel = mockSubchannels.poll(); @@ -2212,16 +2248,44 @@ private void pickFirstModeFallback(long timeout) throws Exception { lbResponseObserver.onNext(buildInitialResponse()); lbResponseObserver.onNext(buildLbResponse(backends1)); - // subchannel should be updated, NOT recreated - inOrder.verify(helper, never()).createSubchannel(any(CreateSubchannelArgs.class)); - assertThat(mockSubchannels).isEmpty(); - // The child LB internally calls updateAddresses on the existing subchannel - verify(subchannel).updateAddresses( - eq(Arrays.asList( - new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001")), - new EquivalentAddressGroup(backends1.get(1).addr, - eagAttrsWithToken("token0002"))))); - inOrder.verify(helper, atLeast(1)).updateBalancingState(eq(READY), pickerCaptor.capture()); + if (PickFirstLoadBalancerProvider.isEnabledNewPickFirst()) { + // In new PF, active fallback subchannel is shut down because its address is not in backends1 + verify(subchannel).shutdown(); + // And LB state transitions to IDLE with RequestConnectionPicker + inOrder.verify(helper, atLeast(1)).updateBalancingState(eq(IDLE), pickerCaptor.capture()); + RoundRobinPicker pickerIdle = (RoundRobinPicker) pickerCaptor.getValue(); + ChildLbPickerEntry idleEntry = (ChildLbPickerEntry) pickerIdle.pickList.get(0); + + // Picking while IDLE triggers requestConnection(), creating a subchannel for backends1.get(0) + PickSubchannelArgs args = mock(PickSubchannelArgs.class); + PickResult pick = idleEntry.getChildPicker().pickSubchannel(args); + assertThat(pick.getSubchannel()).isNull(); // BUFFERing while IDLE + + inOrder.verify(helper).createSubchannel(createSubchannelArgsCaptor.capture()); + CreateSubchannelArgs createSubchannelArgs2 = createSubchannelArgsCaptor.getValue(); + assertThat(createSubchannelArgs2.getAddresses()) + .containsExactly( + new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001"))); + assertThat(mockSubchannels).hasSize(1); + subchannel = mockSubchannels.poll(); + verify(subchannel).requestConnection(); + + // subchannel becomes READY + deliverSubchannelState(subchannel, ConnectivityStateInfo.forNonError(READY)); + inOrder.verify(helper, atLeast(1)).updateBalancingState(eq(READY), pickerCaptor.capture()); + } else { + // subchannel should be updated, NOT recreated + inOrder.verify(helper, never()).createSubchannel(any(CreateSubchannelArgs.class)); + assertThat(mockSubchannels).isEmpty(); + // The child LB internally calls updateAddresses on the existing subchannel + verify(subchannel).updateAddresses( + eq(Arrays.asList( + new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001")), + new EquivalentAddressGroup(backends1.get(1).addr, + eagAttrsWithToken("token0002"))))); + inOrder.verify(helper, atLeast(1)).updateBalancingState(eq(READY), pickerCaptor.capture()); + } + RoundRobinPicker picker2 = (RoundRobinPicker) pickerCaptor.getValue(); assertThat(picker2.dropList).containsExactly(null, null); @@ -2247,7 +2311,8 @@ private void pickFirstModeFallback(long timeout) throws Exception { verify(subchannel, times(2)).requestConnection(); balancer.requestConnection(); - verify(subchannel, times(3)).requestConnection(); + int expectedRequests = PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? 2 : 3; + verify(subchannel, times(expectedRequests)).requestConnection(); // PICK_FIRST doesn't use subchannelPool verify(subchannelPool, never()) @@ -2334,10 +2399,16 @@ public void switchMode() throws Exception { // PICK_FIRST Subchannel: child LB creates it inOrder.verify(helper).createSubchannel(createSubchannelArgsCaptor.capture()); CreateSubchannelArgs createSubchannelArgs = createSubchannelArgsCaptor.getValue(); - assertThat(createSubchannelArgs.getAddresses()) - .containsExactly( - new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001")), - new EquivalentAddressGroup(backends1.get(1).addr, eagAttrsWithToken("token0002"))); + if (PickFirstLoadBalancerProvider.isEnabledNewPickFirst()) { + assertThat(createSubchannelArgs.getAddresses()) + .containsExactly( + new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001"))); + } else { + assertThat(createSubchannelArgs.getAddresses()) + .containsExactly( + new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001")), + new EquivalentAddressGroup(backends1.get(1).addr, eagAttrsWithToken("token0002"))); + } // Child pick_first eagerly connects, so initial state is CONNECTING (not IDLE) inOrder.verify(helper, atLeast(1)) @@ -2424,10 +2495,16 @@ public void switchMode_nullLbPolicy() throws Exception { // PICK_FIRST Subchannel: with delegation, child LB creates the subchannel inOrder.verify(helper).createSubchannel(createSubchannelArgsCaptor.capture()); CreateSubchannelArgs createSubchannelArgs = createSubchannelArgsCaptor.getValue(); - assertThat(createSubchannelArgs.getAddresses()) - .containsExactly( - new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001")), - new EquivalentAddressGroup(backends1.get(1).addr, eagAttrsWithToken("token0002"))); + if (PickFirstLoadBalancerProvider.isEnabledNewPickFirst()) { + assertThat(createSubchannelArgs.getAddresses()) + .containsExactly( + new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001"))); + } else { + assertThat(createSubchannelArgs.getAddresses()) + .containsExactly( + new EquivalentAddressGroup(backends1.get(0).addr, eagAttrsWithToken("token0001")), + new EquivalentAddressGroup(backends1.get(1).addr, eagAttrsWithToken("token0002"))); + } // Child pick_first eagerly connects, so state is CONNECTING (not IDLE) inOrder.verify(helper, atLeast(1)) diff --git a/rls/src/test/java/io/grpc/rls/RlsLoadBalancerTest.java b/rls/src/test/java/io/grpc/rls/RlsLoadBalancerTest.java index 79c9a95b119..714f23559d8 100644 --- a/rls/src/test/java/io/grpc/rls/RlsLoadBalancerTest.java +++ b/rls/src/test/java/io/grpc/rls/RlsLoadBalancerTest.java @@ -73,6 +73,7 @@ import io.grpc.inprocess.InProcessServerBuilder; import io.grpc.internal.FakeClock; import io.grpc.internal.JsonParser; +import io.grpc.internal.PickFirstLoadBalancerProvider; import io.grpc.internal.PickSubchannelArgsImpl; import io.grpc.internal.testing.StreamRecorder; import io.grpc.lookup.v1.RouteLookupServiceGrpc; @@ -257,6 +258,9 @@ public void lb_working_withDefaultTarget_rlsResponding() throws Exception { InOrder inOrder = inOrder(helper); inOrder.verify(helper) .updateBalancingState(eq(ConnectivityState.CONNECTING), pickerCaptor.capture()); + if (PickFirstLoadBalancerProvider.isEnabledNewPickFirst()) { + inOrder.verify(helper).createSubchannel(any(CreateSubchannelArgs.class)); + } SubchannelPicker picker = pickerCaptor.getValue(); // Warm-up pick; will be queued PickResult res = picker.pickSubchannel(searchSubchannelArgs); diff --git a/util/src/test/java/io/grpc/util/RoundRobinLoadBalancerTest.java b/util/src/test/java/io/grpc/util/RoundRobinLoadBalancerTest.java index c0f5bbc526f..06473117a26 100644 --- a/util/src/test/java/io/grpc/util/RoundRobinLoadBalancerTest.java +++ b/util/src/test/java/io/grpc/util/RoundRobinLoadBalancerTest.java @@ -255,7 +255,11 @@ public void pickAfterStateChange() throws Exception { assertThat(pickerCaptor.getValue().pickSubchannel(mockArgs).getStatus()).isEqualTo(error); deliverSubchannelState(subchannel, ConnectivityStateInfo.forNonError(IDLE)); - inOrder.verify(mockHelper).refreshNameResolution(); + if (PickFirstLoadBalancerProvider.isEnabledNewPickFirst()) { + inOrder.verify(mockHelper, never()).refreshNameResolution(); + } else { + inOrder.verify(mockHelper).refreshNameResolution(); + } inOrder.verify(mockHelper, never()) .updateBalancingState(eq(TRANSIENT_FAILURE), any(SubchannelPicker.class)); diff --git a/xds/src/test/java/io/grpc/xds/LeastRequestLoadBalancerTest.java b/xds/src/test/java/io/grpc/xds/LeastRequestLoadBalancerTest.java index 302faed95a4..71d4bdb224b 100644 --- a/xds/src/test/java/io/grpc/xds/LeastRequestLoadBalancerTest.java +++ b/xds/src/test/java/io/grpc/xds/LeastRequestLoadBalancerTest.java @@ -257,7 +257,9 @@ public void pickAfterStateChange() throws Exception { .isEqualTo(PickResult.withNoResult()); deliverSubchannelState(subchannel, ConnectivityStateInfo.forNonError(IDLE)); - inOrder.verify(helper).refreshNameResolution(); + if (!PickFirstLoadBalancerProvider.isEnabledNewPickFirst()) { + inOrder.verify(helper).refreshNameResolution(); + } assertThat(childLbState.getCurrentState()).isEqualTo(TRANSIENT_FAILURE); assertThat(childLbState.getCurrentPicker().toString()).contains(error.toString()); diff --git a/xds/src/test/java/io/grpc/xds/RingHashLoadBalancerTest.java b/xds/src/test/java/io/grpc/xds/RingHashLoadBalancerTest.java index da11df24af4..9c7f8dc62e0 100644 --- a/xds/src/test/java/io/grpc/xds/RingHashLoadBalancerTest.java +++ b/xds/src/test/java/io/grpc/xds/RingHashLoadBalancerTest.java @@ -552,7 +552,10 @@ public void pickWithRandomHash_firstSubchannelInTransientFailure_remainingSubcha assertThat(result.getSubchannel()).isNull(); // buffer request assertThat(result.getDelayType()).isEqualTo("connecting"); assertThat(result.getDelayReason()).isEqualTo("ring_hash: waiting for connection"); - verifyConnection(1); + int expectedCount = + PickFirstLoadBalancerProvider.isEnabledNewPickFirst() + ? (connectionRequestedQueue.isEmpty() ? 0 : 1) : 1; + verifyConnection(expectedCount); } private Subchannel getSubChannel(EquivalentAddressGroup eag) { @@ -655,11 +658,10 @@ public void skipFailingHosts_firstTwoHostsFailed_pickNextFirstReady() { ConnectivityStateInfo.forTransientFailure( Status.PERMISSION_DENIED.withDescription("permission denied"))); verify(helper).updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture()); - verifyConnection(2); + verifyConnection(PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? 1 : 2); PickResult result = pickerCaptor.getValue().pickSubchannel(args); // activate last subchannel assertThat(result.getStatus().isOk()).isTrue(); - int expectedCount = PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? 0 : 1; - verifyConnection(expectedCount); + verifyConnection(PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? 0 : 1); deliverSubchannelState( getSubchannel(servers, 0), @@ -727,7 +729,7 @@ public void allSubchannelsInTransientFailure() { } verify(helper, atLeastOnce()) .updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture()); - verifyConnection(2); + verifyConnection(PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? 1 : 2); // Picking subchannel triggers connection. RPC hash hits server0. PickSubchannelArgs args = getDefaultPickSubchannelArgsForServer(0); @@ -812,7 +814,9 @@ public void firstSubchannelFailure() { assertThat(result.getStatus().isOk()).isTrue(); assertThat(result.getSubchannel()).isNull(); verify(subchannelList.get(0), never()).requestConnection(); // In TF - verify(subchannelList.get(1)).requestConnection(); + verify(subchannelList.get(1), + PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? never() : times(1)) + .requestConnection(); verify(subchannelList.get(2), never()).requestConnection(); // Not one of the first 2 } @@ -840,11 +844,11 @@ public void secondSubchannelConnecting() { // Picking subchannel when idle triggers connection. deliverSubchannelState(getSubchannel(servers, 2), ConnectivityStateInfo.forNonError(IDLE)); - verifyConnection(1); + verifyConnection(PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? 0 : 1); PickSubchannelArgs args = getDefaultPickSubchannelArgs(hashFunc.hashVoid()); PickResult result = pickerCaptor.getValue().pickSubchannel(args); assertThat(result.getStatus().isOk()).isTrue(); - verifyConnection(1); + verifyConnection(PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? 0 : 1); } @Test @@ -864,14 +868,16 @@ public void secondSubchannelFailure() { deliverSubchannelUnreachable(firstSubchannel); deliverSubchannelUnreachable(getSubchannel(servers, 2)); verify(helper).updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture()); - verifyConnection(2); + verifyConnection(PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? 1 : 2); // Picking subchannel triggers connection. PickSubchannelArgs args = getDefaultPickSubchannelArgs(hashFunc.hashVoid()); PickResult result = pickerCaptor.getValue().pickSubchannel(args); assertThat(result.getStatus().isOk()).isTrue(); - verify(getSubchannel(servers, 1)).requestConnection(); - verifyConnection(1); + verify(getSubchannel(servers, 1), + PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? never() : times(1)) + .requestConnection(); + verifyConnection(PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? 0 : 1); } @Test @@ -894,7 +900,7 @@ public void thirdSubchannelConnecting() { deliverSubchannelState(getSubchannel(servers, 1), CSI_CONNECTING); verify(helper, atLeastOnce()) .updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture()); - verifyConnection(2); + verifyConnection(PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? 1 : 2); // Picking subchannel should not trigger connection per gRFC A61. PickSubchannelArgs args = getDefaultPickSubchannelArgs(hashFunc.hashVoid()); @@ -929,7 +935,9 @@ public void stickyTransientFailure() { PickSubchannelArgs args = getDefaultPickSubchannelArgs(hashFunc.hashVoid()); PickResult result = pickerCaptor.getValue().pickSubchannel(args); assertThat(result.getStatus().isOk()).isTrue(); - verify(getSubchannel(servers, 1)).requestConnection(); + verify(getSubchannel(servers, 1), + PickFirstLoadBalancerProvider.isEnabledNewPickFirst() ? never() : times(1)) + .requestConnection(); verify(getSubchannel(servers, 2), never()).requestConnection(); }