core: Don't reuse channels in PickFirstLeafLB test · grpc/grpc-java@e567b44
@@ -123,16 +123,14 @@ public void uncaughtException(Thread t, Throwable e) {
123123private ArgumentCaptor<CreateSubchannelArgs> createArgsCaptor;
124124@Captor
125125private ArgumentCaptor<SubchannelStateListener> stateListenerCaptor;
126-private final Helper mockHelper = mock(Helper.class, delegatesTo(new MockHelperImpl()));
127-@Mock
126+private Helper mockHelper;
128127private FakeSubchannel mockSubchannel1;
129-@Mock
128+private FakeSubchannel mockSubchannel1n2;
130129private FakeSubchannel mockSubchannel2;
131-@Mock
130+private FakeSubchannel mockSubchannel2n2;
132131private FakeSubchannel mockSubchannel3;
133-@Mock
132+private FakeSubchannel mockSubchannel3n2;
134133private FakeSubchannel mockSubchannel4;
135-@Mock
136134private FakeSubchannel mockSubchannel5;
137135@Mock // This LoadBalancer doesn't use any of the arg fields, as verified in tearDown().
138136private PickSubchannelArgs mockArgs;
@@ -150,23 +148,28 @@ public void setUp() {
150148SocketAddress addr = new FakeSocketAddress("server" + i);
151149servers.add(new EquivalentAddressGroup(addr));
152150 }
153-mockSubchannel1 = mock(FakeSubchannel.class);
154-mockSubchannel2 = mock(FakeSubchannel.class);
155-mockSubchannel3 = mock(FakeSubchannel.class);
156-mockSubchannel4 = mock(FakeSubchannel.class);
157-mockSubchannel5 = mock(FakeSubchannel.class);
158-when(mockSubchannel1.getAttributes()).thenReturn(Attributes.EMPTY);
159-when(mockSubchannel2.getAttributes()).thenReturn(Attributes.EMPTY);
160-when(mockSubchannel3.getAttributes()).thenReturn(Attributes.EMPTY);
161-when(mockSubchannel4.getAttributes()).thenReturn(Attributes.EMPTY);
162-when(mockSubchannel5.getAttributes()).thenReturn(Attributes.EMPTY);
163-164-when(mockSubchannel1.getAllAddresses()).thenReturn(Lists.newArrayList(servers.get(0)));
165-when(mockSubchannel2.getAllAddresses()).thenReturn(Lists.newArrayList(servers.get(1)));
166-when(mockSubchannel3.getAllAddresses()).thenReturn(Lists.newArrayList(servers.get(2)));
167-when(mockSubchannel4.getAllAddresses()).thenReturn(Lists.newArrayList(servers.get(3)));
168-when(mockSubchannel5.getAllAddresses()).thenReturn(Lists.newArrayList(servers.get(4)));
169-151+mockSubchannel1 = mock(FakeSubchannel.class, delegatesTo(
152+new FakeSubchannel(Arrays.asList(servers.get(0)), Attributes.EMPTY)));
153+mockSubchannel1n2 = mock(FakeSubchannel.class, delegatesTo(
154+new FakeSubchannel(Arrays.asList(servers.get(0)), Attributes.EMPTY)));
155+mockSubchannel2 = mock(FakeSubchannel.class, delegatesTo(
156+new FakeSubchannel(Arrays.asList(servers.get(1)), Attributes.EMPTY)));
157+mockSubchannel2n2 = mock(FakeSubchannel.class, delegatesTo(
158+new FakeSubchannel(Arrays.asList(servers.get(1)), Attributes.EMPTY)));
159+mockSubchannel3 = mock(FakeSubchannel.class, delegatesTo(
160+new FakeSubchannel(Arrays.asList(servers.get(2)), Attributes.EMPTY)));
161+mockSubchannel3n2 = mock(FakeSubchannel.class, delegatesTo(
162+new FakeSubchannel(Arrays.asList(servers.get(2)), Attributes.EMPTY)));
163+mockSubchannel4 = mock(FakeSubchannel.class, delegatesTo(
164+new FakeSubchannel(Arrays.asList(servers.get(3)), Attributes.EMPTY)));
165+mockSubchannel5 = mock(FakeSubchannel.class, delegatesTo(
166+new FakeSubchannel(Arrays.asList(servers.get(4)), Attributes.EMPTY)));
167+168+mockHelper = mock(Helper.class, delegatesTo(new MockHelperImpl(Arrays.asList(
169+mockSubchannel1, mockSubchannel1n2,
170+mockSubchannel2, mockSubchannel2n2,
171+mockSubchannel3, mockSubchannel3n2,
172+mockSubchannel4, mockSubchannel5))));
170173loadBalancer = new PickFirstLeafLoadBalancer(mockHelper);
171174 }
172175@@ -251,14 +254,14 @@ public void pickAfterResolved_shuffle() {
251254PickResult pick2 = pickerCaptor.getValue().pickSubchannel(mockArgs);
252255assertEquals(pick1, pick2);
253256verifyNoMoreInteractions(mockHelper);
254-assertThat(pick1.toString()).contains("subchannel=null");
257+assertThat(pick1.getSubchannel()).isNull();
255258256259stateListener2.onSubchannelState(ConnectivityStateInfo.forNonError(READY));
257260verify(mockHelper).updateBalancingState(eq(READY), pickerCaptor.capture());
258261PickResult pick3 = pickerCaptor.getValue().pickSubchannel(mockArgs);
259262PickResult pick4 = pickerCaptor.getValue().pickSubchannel(mockArgs);
260263assertEquals(pick3, pick4);
261-assertThat(pick3.toString()).contains("subchannel=Mock");
264+assertThat(pick3.getSubchannel()).isEqualTo(mockSubchannel2);
262265 }
263266264267@Test
@@ -569,7 +572,7 @@ public void pickWithDupAddressesUpDownUp() {
569572InOrder inOrder = inOrder(mockHelper);
570573SocketAddress socketAddress = servers.get(0).getAddresses().get(0);
571574EquivalentAddressGroup badEag = new EquivalentAddressGroup(
572-Lists.newArrayList(socketAddress, socketAddress), affinity);
575+Lists.newArrayList(socketAddress, socketAddress));
573576List<EquivalentAddressGroup> newServers = Lists.newArrayList(badEag);
574577575578loadBalancer.acceptResolvedAddresses(
@@ -727,7 +730,7 @@ public void nameResolutionSuccessAfterError() {
727730@Test
728731public void nameResolutionTemporaryError() {
729732List<EquivalentAddressGroup> newServers = Lists.newArrayList(servers.get(0));
730-InOrder inOrder = inOrder(mockHelper, mockSubchannel1);
733+InOrder inOrder = inOrder(mockHelper, mockSubchannel1, mockSubchannel1n2);
731734loadBalancer.acceptResolvedAddresses(
732735ResolvedAddresses.newBuilder().setAddresses(newServers).setAttributes(affinity).build());
733736inOrder.verify(mockSubchannel1).start(stateListenerCaptor.capture());
@@ -744,14 +747,15 @@ public void nameResolutionTemporaryError() {
744747loadBalancer.acceptResolvedAddresses(
745748ResolvedAddresses.newBuilder().setAddresses(servers).setAttributes(affinity).build());
746749inOrder.verify(mockHelper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
747-inOrder.verify(mockSubchannel1).start(stateListenerCaptor.capture());
750+inOrder.verify(mockSubchannel1n2).start(stateListenerCaptor.capture());
748751SubchannelStateListener stateListener2 = stateListenerCaptor.getValue();
749752750753assertNull(pickerCaptor.getValue().pickSubchannel(mockArgs).getSubchannel());
751754752755stateListener2.onSubchannelState(ConnectivityStateInfo.forNonError(READY));
753756inOrder.verify(mockHelper).updateBalancingState(eq(READY), pickerCaptor.capture());
754-assertEquals(mockSubchannel1, pickerCaptor.getValue().pickSubchannel(mockArgs).getSubchannel());
757+assertEquals(mockSubchannel1n2,
758+pickerCaptor.getValue().pickSubchannel(mockArgs).getSubchannel());
755759 }
756760757761@@ -1027,7 +1031,7 @@ public void updateAddresses_disjoint_connecting() {
10271031@Test
10281032public void updateAddresses_disjoint_ready_twice() {
10291033InOrder inOrder = inOrder(mockHelper, mockSubchannel1, mockSubchannel2,
1030-mockSubchannel3, mockSubchannel4);
1034+mockSubchannel3, mockSubchannel4, mockSubchannel1n2, mockSubchannel2n2);
10311035// Creating first set of endpoints/addresses
10321036List<EquivalentAddressGroup> oldServers = Lists.newArrayList(servers.get(0), servers.get(1));
10331037SubchannelStateListener stateListener2 = null;
@@ -1126,7 +1130,7 @@ public void updateAddresses_disjoint_ready_twice() {
11261130ResolvedAddresses.newBuilder().setAddresses(newestServers).setAttributes(affinity).build());
11271131inOrder.verify(mockSubchannel3).shutdown();
11281132inOrder.verify(mockHelper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
1129-inOrder.verify(mockSubchannel1).start(stateListenerCaptor.capture());
1133+inOrder.verify(mockSubchannel1n2).start(stateListenerCaptor.capture());
11301134stateListener = stateListenerCaptor.getValue();
11311135assertEquals(CONNECTING, loadBalancer.getConcludedConnectivityState());
11321136picker = pickerCaptor.getValue();
@@ -1135,7 +1139,7 @@ public void updateAddresses_disjoint_ready_twice() {
11351139assertEquals(picker.pickSubchannel(mockArgs), picker.pickSubchannel(mockArgs));
1136114011371141// But the picker calls requestConnection() only once
1138-inOrder.verify(mockSubchannel1).requestConnection();
1142+inOrder.verify(mockSubchannel1n2).requestConnection();
11391143assertEquals(PickResult.withNoResult(), pickerCaptor.getValue().pickSubchannel(mockArgs));
11401144assertEquals(CONNECTING, loadBalancer.getConcludedConnectivityState());
11411145@@ -1150,23 +1154,24 @@ public void updateAddresses_disjoint_ready_twice() {
11501154stateListener.onSubchannelState(ConnectivityStateInfo.forTransientFailure(CONNECTION_ERROR));
1151115511521156// Starting connection attempt to address 2
1153-if (!enableHappyEyeballs) {
1154-inOrder.verify(mockSubchannel2).start(stateListenerCaptor.capture());
1155- stateListener2 = stateListenerCaptor.getValue();
1156-}
1157-inOrder.verify(mockSubchannel2).requestConnection();
1157+FakeSubchannel mockSubchannel2Attempt =
1158+ enableHappyEyeballs ? mockSubchannel2n2 : mockSubchannel2;
1159+inOrder.verify(mockSubchannel2Attempt).start(stateListenerCaptor.capture());
1160+stateListener2 = stateListenerCaptor.getValue();
1161+inOrder.verify(mockSubchannel2Attempt).requestConnection();
1158116211591163// Connection attempt to address 2 is successful
11601164stateListener2.onSubchannelState(ConnectivityStateInfo.forNonError(READY));
11611165assertEquals(READY, loadBalancer.getConcludedConnectivityState());
1162-inOrder.verify(mockSubchannel1).shutdown();
1166+inOrder.verify(mockSubchannel1n2).shutdown();
1163116711641168// Successful connection shuts down other subchannel
11651169inOrder.verify(mockHelper).updateBalancingState(eq(READY), pickerCaptor.capture());
11661170picker = pickerCaptor.getValue();
1167117111681172// Verify that picker still returns correct subchannel
1169-assertEquals(PickResult.withSubchannel(mockSubchannel2), picker.pickSubchannel(mockArgs));
1173+assertEquals(
1174+PickResult.withSubchannel(mockSubchannel2Attempt), picker.pickSubchannel(mockArgs));
11701175 }
1171117611721177@Test
@@ -2048,7 +2053,7 @@ public void recreate_shutdown_subchannel() {
2048205320492054// Starting first connection attempt
20502055InOrder inOrder = inOrder(mockHelper, mockSubchannel1, mockSubchannel2,
2051-mockSubchannel3, mockSubchannel4); // captor: captures
2056+mockSubchannel3, mockSubchannel4, mockSubchannel1n2); // captor: captures
2052205720532058// Creating first set of endpoints/addresses
20542059List<EquivalentAddressGroup> addrs =
@@ -2084,9 +2089,9 @@ public void recreate_shutdown_subchannel() {
2084208920852090// Calling pickSubchannel() requests a connection.
20862091assertEquals(picker.pickSubchannel(mockArgs), picker.pickSubchannel(mockArgs));
2087-inOrder.verify(mockSubchannel1).start(stateListenerCaptor.capture());
2092+inOrder.verify(mockSubchannel1n2).start(stateListenerCaptor.capture());
20882093SubchannelStateListener stateListener3 = stateListenerCaptor.getValue();
2089-inOrder.verify(mockSubchannel1).requestConnection();
2094+inOrder.verify(mockSubchannel1n2).requestConnection();
20902095when(mockSubchannel1.getAllAddresses()).thenReturn(Lists.newArrayList(servers.get(0)));
2091209620922097// gives the same result when called twice
@@ -2101,7 +2106,7 @@ public void recreate_shutdown_subchannel() {
21012106// second subchannel connection attempt succeeds
21022107inOrder.verify(mockSubchannel2).requestConnection();
21032108stateListener2.onSubchannelState(ConnectivityStateInfo.forNonError(READY));
2104-inOrder.verify(mockSubchannel1).shutdown();
2109+inOrder.verify(mockSubchannel1n2).shutdown();
21052110inOrder.verify(mockHelper).updateBalancingState(eq(READY), pickerCaptor.capture());
21062111assertEquals(READY, loadBalancer.getConcludedConnectivityState());
21072112@@ -2146,7 +2151,7 @@ public void shutdown() {
21462151public void ready_then_transient_failure_again() {
21472152// Starting first connection attempt
21482153InOrder inOrder = inOrder(mockHelper, mockSubchannel1, mockSubchannel2,
2149-mockSubchannel3, mockSubchannel4); // captor: captures
2154+mockSubchannel3, mockSubchannel4, mockSubchannel1n2); // captor: captures
2150215521512156// Creating first set of endpoints/addresses
21522157List<EquivalentAddressGroup> addrs =
@@ -2183,9 +2188,9 @@ public void ready_then_transient_failure_again() {
2183218821842189// Calling pickSubchannel() requests a connection, gives the same result when called twice.
21852190assertEquals(picker.pickSubchannel(mockArgs), picker.pickSubchannel(mockArgs));
2186-inOrder.verify(mockSubchannel1).start(stateListenerCaptor.capture());
2191+inOrder.verify(mockSubchannel1n2).start(stateListenerCaptor.capture());
21872192SubchannelStateListener stateListener3 = stateListenerCaptor.getValue();
2188-inOrder.verify(mockSubchannel1).requestConnection();
2193+inOrder.verify(mockSubchannel1n2).requestConnection();
21892194when(mockSubchannel3.getAllAddresses()).thenReturn(Lists.newArrayList(servers.get(0)));
21902195stateListener3.onSubchannelState(ConnectivityStateInfo.forNonError(CONNECTING));
21912196inOrder.verify(mockHelper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
@@ -2201,7 +2206,7 @@ public void ready_then_transient_failure_again() {
22012206assertEquals(READY, loadBalancer.getConcludedConnectivityState());
2202220722032208// verify that picker returns correct subchannel
2204-inOrder.verify(mockSubchannel1).shutdown();
2209+inOrder.verify(mockSubchannel1n2).shutdown();
22052210inOrder.verify(mockHelper).updateBalancingState(eq(READY), pickerCaptor.capture());
22062211picker = pickerCaptor.getValue();
22072212assertEquals(PickResult.withSubchannel(mockSubchannel2), picker.pickSubchannel(mockArgs));
@@ -2309,7 +2314,8 @@ public void happy_eyeballs_connection_results_happen_after_get_to_end() {
23092314public void happy_eyeballs_pick_pushes_index_over_end() {
23102315Assume.assumeTrue(enableHappyEyeballs); // This test is only for happy eyeballs
231123162312-InOrder inOrder = inOrder(mockHelper, mockSubchannel1, mockSubchannel2, mockSubchannel3);
2317+InOrder inOrder = inOrder(mockHelper, mockSubchannel1, mockSubchannel2, mockSubchannel3,
2318+mockSubchannel2n2, mockSubchannel3n2);
23132319Status error = Status.UNAUTHENTICATED.withDescription("simulated failure");
2314232023152321List<EquivalentAddressGroup> addrs =
@@ -2359,9 +2365,9 @@ public void happy_eyeballs_pick_pushes_index_over_end() {
2359236523602366// Try pushing after end with just picks
23612367listeners[0].onSubchannelState(ConnectivityStateInfo.forNonError(READY));
2362-for (SubchannelStateListener listener : listeners) {
2363- listener.onSubchannelState(ConnectivityStateInfo.forNonError(IDLE));
2364-}
2368+verify(mockSubchannel2).shutdown();
2369+verify(mockSubchannel3).shutdown();
2370+listeners[0].onSubchannelState(ConnectivityStateInfo.forNonError(IDLE));
23652371loadBalancer.acceptResolvedAddresses(
23662372ResolvedAddresses.newBuilder().setAddresses(addrs).setAttributes(affinity).build());
23672373inOrder.verify(mockHelper).updateBalancingState(eq(IDLE), pickerCaptor.capture());
@@ -2372,11 +2378,14 @@ public void happy_eyeballs_pick_pushes_index_over_end() {
23722378 }
23732379assertEquals(IDLE, loadBalancer.getConcludedConnectivityState());
237423802375-for (SubchannelStateListener listener : listeners) {
2376-listener.onSubchannelState(ConnectivityStateInfo.forTransientFailure(error));
2377- }
2381+listeners[0].onSubchannelState(ConnectivityStateInfo.forTransientFailure(error));
2382+inOrder.verify(mockSubchannel2n2).start(stateListenerCaptor.capture());
2383+stateListenerCaptor.getValue().onSubchannelState(
2384+ConnectivityStateInfo.forTransientFailure(error));
2385+inOrder.verify(mockSubchannel3n2).start(stateListenerCaptor.capture());
2386+stateListenerCaptor.getValue().onSubchannelState(
2387+ConnectivityStateInfo.forTransientFailure(error));
23782388assertEquals(TRANSIENT_FAILURE, loadBalancer.getConcludedConnectivityState());
2379-23802389 }
2381239023822391@Test
@@ -2571,9 +2580,22 @@ private static class FakeSocketAddress extends SocketAddress {
2571258025722581@Override
25732582public String toString() {
2574-return "FakeSocketAddress-" + name;
2583+return "FakeSocketAddress(" + name + ")";
2584+ }
2585+2586+@Override
2587+public boolean equals(Object o) {
2588+if (!(o instanceof FakeSocketAddress)) {
2589+return false;
2590+ }
2591+FakeSocketAddress that = (FakeSocketAddress) o;
2592+return this.name.equals(that.name);
25752593 }
257625942595+@Override
2596+public int hashCode() {
2597+return name.hashCode();
2598+ }
25772599 }
2578260025792601private void forwardTimeByConnectionDelay() {
@@ -2631,15 +2653,26 @@ public void updateAddresses(List<EquivalentAddressGroup> addrs) {
2631265326322654@Override
26332655public void shutdown() {
2656+listener.onSubchannelState(ConnectivityStateInfo.forNonError(SHUTDOWN));
26342657 }
2635265826362659@Override
26372660public void requestConnection() {
2638-listener.onSubchannelState(ConnectivityStateInfo.forNonError(CONNECTING));
2661+ }
2662+2663+@Override
2664+public String toString() {
2665+return "FakeSubchannel@" + hashCode() + "(" + eags + ")";
26392666 }
26402667 }
2641266826422669private class MockHelperImpl extends LoadBalancer.Helper {
2670+private final List<Subchannel> subchannels;
2671+2672+public MockHelperImpl(List<? extends Subchannel> subchannels) {
2673+this.subchannels = new ArrayList<Subchannel>(subchannels);
2674+ }
2675+26432676@Override
26442677public ManagedChannel createOobChannel(EquivalentAddressGroup eag, String authority) {
26452678return null;
@@ -2672,16 +2705,17 @@ public void refreshNameResolution() {
2672270526732706@Override
26742707public Subchannel createSubchannel(CreateSubchannelArgs args) {
2675-SocketAddress addr = args.getAddresses().get(0).getAddresses().get(0);
2676-List<FakeSubchannel> fakeSubchannels =
2677-Arrays.asList(mockSubchannel1, mockSubchannel2, mockSubchannel3, mockSubchannel4,
2678-mockSubchannel5);
2679-for (int i = 1; i <= 5; i++) {
2680-if (addr.toString().equals(new FakeSocketAddress("server" + i).toString())) {
2681-return fakeSubchannels.get(i - 1);
2708+for (int i = 0; i < subchannels.size(); i++) {
2709+Subchannel subchannel = subchannels.get(i);
2710+List<EquivalentAddressGroup> addrs = subchannel.getAllAddresses();
2711+verify(subchannel, atLeast(1)).getAllAddresses(); // ignore the interaction
2712+if (!args.getAddresses().equals(addrs)) {
2713+continue;
26822714 }
2715+subchannels.remove(i);
2716+return subchannel;
26832717 }
2684-throw new IllegalArgumentException("Unexpected address: " + addr);
2718+throw new IllegalArgumentException("Unexpected addresses: " + args.getAddresses());
26852719 }
26862720 }
2687-}
2721+}