@@ -123,16 +123,14 @@ public void uncaughtException(Thread t, Throwable e) {
123123 private ArgumentCaptor <CreateSubchannelArgs > createArgsCaptor ;
124124 @ Captor
125125 private ArgumentCaptor <SubchannelStateListener > stateListenerCaptor ;
126- private final Helper mockHelper = mock (Helper .class , delegatesTo (new MockHelperImpl ()));
127- @ Mock
126+ private Helper mockHelper ;
128127 private FakeSubchannel mockSubchannel1 ;
129- @ Mock
128+ private FakeSubchannel mockSubchannel1n2 ;
130129 private FakeSubchannel mockSubchannel2 ;
131- @ Mock
130+ private FakeSubchannel mockSubchannel2n2 ;
132131 private FakeSubchannel mockSubchannel3 ;
133- @ Mock
132+ private FakeSubchannel mockSubchannel3n2 ;
134133 private FakeSubchannel mockSubchannel4 ;
135- @ Mock
136134 private FakeSubchannel mockSubchannel5 ;
137135 @ Mock // This LoadBalancer doesn't use any of the arg fields, as verified in tearDown().
138136 private PickSubchannelArgs mockArgs ;
@@ -150,23 +148,28 @@ public void setUp() {
150148 SocketAddress addr = new FakeSocketAddress ("server" + i );
151149 servers .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 ))));
170173 loadBalancer = new PickFirstLeafLoadBalancer (mockHelper );
171174 }
172175
@@ -251,14 +254,14 @@ public void pickAfterResolved_shuffle() {
251254 PickResult pick2 = pickerCaptor .getValue ().pickSubchannel (mockArgs );
252255 assertEquals (pick1 , pick2 );
253256 verifyNoMoreInteractions (mockHelper );
254- assertThat (pick1 .toString ()).contains ( "subchannel=null" );
257+ assertThat (pick1 .getSubchannel ()).isNull ( );
255258
256259 stateListener2 .onSubchannelState (ConnectivityStateInfo .forNonError (READY ));
257260 verify (mockHelper ).updateBalancingState (eq (READY ), pickerCaptor .capture ());
258261 PickResult pick3 = pickerCaptor .getValue ().pickSubchannel (mockArgs );
259262 PickResult pick4 = pickerCaptor .getValue ().pickSubchannel (mockArgs );
260263 assertEquals (pick3 , pick4 );
261- assertThat (pick3 .toString ()).contains ( "subchannel=Mock" );
264+ assertThat (pick3 .getSubchannel ()).isEqualTo ( mockSubchannel2 );
262265 }
263266
264267 @ Test
@@ -569,7 +572,7 @@ public void pickWithDupAddressesUpDownUp() {
569572 InOrder inOrder = inOrder (mockHelper );
570573 SocketAddress socketAddress = servers .get (0 ).getAddresses ().get (0 );
571574 EquivalentAddressGroup badEag = new EquivalentAddressGroup (
572- Lists .newArrayList (socketAddress , socketAddress ), affinity );
575+ Lists .newArrayList (socketAddress , socketAddress ));
573576 List <EquivalentAddressGroup > newServers = Lists .newArrayList (badEag );
574577
575578 loadBalancer .acceptResolvedAddresses (
@@ -727,7 +730,7 @@ public void nameResolutionSuccessAfterError() {
727730 @ Test
728731 public void nameResolutionTemporaryError () {
729732 List <EquivalentAddressGroup > newServers = Lists .newArrayList (servers .get (0 ));
730- InOrder inOrder = inOrder (mockHelper , mockSubchannel1 );
733+ InOrder inOrder = inOrder (mockHelper , mockSubchannel1 , mockSubchannel1n2 );
731734 loadBalancer .acceptResolvedAddresses (
732735 ResolvedAddresses .newBuilder ().setAddresses (newServers ).setAttributes (affinity ).build ());
733736 inOrder .verify (mockSubchannel1 ).start (stateListenerCaptor .capture ());
@@ -744,14 +747,15 @@ public void nameResolutionTemporaryError() {
744747 loadBalancer .acceptResolvedAddresses (
745748 ResolvedAddresses .newBuilder ().setAddresses (servers ).setAttributes (affinity ).build ());
746749 inOrder .verify (mockHelper ).updateBalancingState (eq (CONNECTING ), pickerCaptor .capture ());
747- inOrder .verify (mockSubchannel1 ).start (stateListenerCaptor .capture ());
750+ inOrder .verify (mockSubchannel1n2 ).start (stateListenerCaptor .capture ());
748751 SubchannelStateListener stateListener2 = stateListenerCaptor .getValue ();
749752
750753 assertNull (pickerCaptor .getValue ().pickSubchannel (mockArgs ).getSubchannel ());
751754
752755 stateListener2 .onSubchannelState (ConnectivityStateInfo .forNonError (READY ));
753756 inOrder .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 }
756760
757761
@@ -1027,7 +1031,7 @@ public void updateAddresses_disjoint_connecting() {
10271031 @ Test
10281032 public void updateAddresses_disjoint_ready_twice () {
10291033 InOrder inOrder = inOrder (mockHelper , mockSubchannel1 , mockSubchannel2 ,
1030- mockSubchannel3 , mockSubchannel4 );
1034+ mockSubchannel3 , mockSubchannel4 , mockSubchannel1n2 , mockSubchannel2n2 );
10311035 // Creating first set of endpoints/addresses
10321036 List <EquivalentAddressGroup > oldServers = Lists .newArrayList (servers .get (0 ), servers .get (1 ));
10331037 SubchannelStateListener stateListener2 = null ;
@@ -1126,7 +1130,7 @@ public void updateAddresses_disjoint_ready_twice() {
11261130 ResolvedAddresses .newBuilder ().setAddresses (newestServers ).setAttributes (affinity ).build ());
11271131 inOrder .verify (mockSubchannel3 ).shutdown ();
11281132 inOrder .verify (mockHelper ).updateBalancingState (eq (CONNECTING ), pickerCaptor .capture ());
1129- inOrder .verify (mockSubchannel1 ).start (stateListenerCaptor .capture ());
1133+ inOrder .verify (mockSubchannel1n2 ).start (stateListenerCaptor .capture ());
11301134 stateListener = stateListenerCaptor .getValue ();
11311135 assertEquals (CONNECTING , loadBalancer .getConcludedConnectivityState ());
11321136 picker = pickerCaptor .getValue ();
@@ -1135,7 +1139,7 @@ public void updateAddresses_disjoint_ready_twice() {
11351139 assertEquals (picker .pickSubchannel (mockArgs ), picker .pickSubchannel (mockArgs ));
11361140
11371141 // But the picker calls requestConnection() only once
1138- inOrder .verify (mockSubchannel1 ).requestConnection ();
1142+ inOrder .verify (mockSubchannel1n2 ).requestConnection ();
11391143 assertEquals (PickResult .withNoResult (), pickerCaptor .getValue ().pickSubchannel (mockArgs ));
11401144 assertEquals (CONNECTING , loadBalancer .getConcludedConnectivityState ());
11411145
@@ -1150,23 +1154,24 @@ public void updateAddresses_disjoint_ready_twice() {
11501154 stateListener .onSubchannelState (ConnectivityStateInfo .forTransientFailure (CONNECTION_ERROR ));
11511155
11521156 // 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 ();
11581162
11591163 // Connection attempt to address 2 is successful
11601164 stateListener2 .onSubchannelState (ConnectivityStateInfo .forNonError (READY ));
11611165 assertEquals (READY , loadBalancer .getConcludedConnectivityState ());
1162- inOrder .verify (mockSubchannel1 ).shutdown ();
1166+ inOrder .verify (mockSubchannel1n2 ).shutdown ();
11631167
11641168 // Successful connection shuts down other subchannel
11651169 inOrder .verify (mockHelper ).updateBalancingState (eq (READY ), pickerCaptor .capture ());
11661170 picker = pickerCaptor .getValue ();
11671171
11681172 // 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 }
11711176
11721177 @ Test
@@ -2048,7 +2053,7 @@ public void recreate_shutdown_subchannel() {
20482053
20492054 // Starting first connection attempt
20502055 InOrder inOrder = inOrder (mockHelper , mockSubchannel1 , mockSubchannel2 ,
2051- mockSubchannel3 , mockSubchannel4 ); // captor: captures
2056+ mockSubchannel3 , mockSubchannel4 , mockSubchannel1n2 ); // captor: captures
20522057
20532058 // Creating first set of endpoints/addresses
20542059 List <EquivalentAddressGroup > addrs =
@@ -2084,9 +2089,9 @@ public void recreate_shutdown_subchannel() {
20842089
20852090 // Calling pickSubchannel() requests a connection.
20862091 assertEquals (picker .pickSubchannel (mockArgs ), picker .pickSubchannel (mockArgs ));
2087- inOrder .verify (mockSubchannel1 ).start (stateListenerCaptor .capture ());
2092+ inOrder .verify (mockSubchannel1n2 ).start (stateListenerCaptor .capture ());
20882093 SubchannelStateListener stateListener3 = stateListenerCaptor .getValue ();
2089- inOrder .verify (mockSubchannel1 ).requestConnection ();
2094+ inOrder .verify (mockSubchannel1n2 ).requestConnection ();
20902095 when (mockSubchannel1 .getAllAddresses ()).thenReturn (Lists .newArrayList (servers .get (0 )));
20912096
20922097 // gives the same result when called twice
@@ -2101,7 +2106,7 @@ public void recreate_shutdown_subchannel() {
21012106 // second subchannel connection attempt succeeds
21022107 inOrder .verify (mockSubchannel2 ).requestConnection ();
21032108 stateListener2 .onSubchannelState (ConnectivityStateInfo .forNonError (READY ));
2104- inOrder .verify (mockSubchannel1 ).shutdown ();
2109+ inOrder .verify (mockSubchannel1n2 ).shutdown ();
21052110 inOrder .verify (mockHelper ).updateBalancingState (eq (READY ), pickerCaptor .capture ());
21062111 assertEquals (READY , loadBalancer .getConcludedConnectivityState ());
21072112
@@ -2146,7 +2151,7 @@ public void shutdown() {
21462151 public void ready_then_transient_failure_again () {
21472152 // Starting first connection attempt
21482153 InOrder inOrder = inOrder (mockHelper , mockSubchannel1 , mockSubchannel2 ,
2149- mockSubchannel3 , mockSubchannel4 ); // captor: captures
2154+ mockSubchannel3 , mockSubchannel4 , mockSubchannel1n2 ); // captor: captures
21502155
21512156 // Creating first set of endpoints/addresses
21522157 List <EquivalentAddressGroup > addrs =
@@ -2183,9 +2188,9 @@ public void ready_then_transient_failure_again() {
21832188
21842189 // Calling pickSubchannel() requests a connection, gives the same result when called twice.
21852190 assertEquals (picker .pickSubchannel (mockArgs ), picker .pickSubchannel (mockArgs ));
2186- inOrder .verify (mockSubchannel1 ).start (stateListenerCaptor .capture ());
2191+ inOrder .verify (mockSubchannel1n2 ).start (stateListenerCaptor .capture ());
21872192 SubchannelStateListener stateListener3 = stateListenerCaptor .getValue ();
2188- inOrder .verify (mockSubchannel1 ).requestConnection ();
2193+ inOrder .verify (mockSubchannel1n2 ).requestConnection ();
21892194 when (mockSubchannel3 .getAllAddresses ()).thenReturn (Lists .newArrayList (servers .get (0 )));
21902195 stateListener3 .onSubchannelState (ConnectivityStateInfo .forNonError (CONNECTING ));
21912196 inOrder .verify (mockHelper ).updateBalancingState (eq (CONNECTING ), pickerCaptor .capture ());
@@ -2201,7 +2206,7 @@ public void ready_then_transient_failure_again() {
22012206 assertEquals (READY , loadBalancer .getConcludedConnectivityState ());
22022207
22032208 // verify that picker returns correct subchannel
2204- inOrder .verify (mockSubchannel1 ).shutdown ();
2209+ inOrder .verify (mockSubchannel1n2 ).shutdown ();
22052210 inOrder .verify (mockHelper ).updateBalancingState (eq (READY ), pickerCaptor .capture ());
22062211 picker = pickerCaptor .getValue ();
22072212 assertEquals (PickResult .withSubchannel (mockSubchannel2 ), picker .pickSubchannel (mockArgs ));
@@ -2309,7 +2314,8 @@ public void happy_eyeballs_connection_results_happen_after_get_to_end() {
23092314 public void happy_eyeballs_pick_pushes_index_over_end () {
23102315 Assume .assumeTrue (enableHappyEyeballs ); // This test is only for happy eyeballs
23112316
2312- InOrder inOrder = inOrder (mockHelper , mockSubchannel1 , mockSubchannel2 , mockSubchannel3 );
2317+ InOrder inOrder = inOrder (mockHelper , mockSubchannel1 , mockSubchannel2 , mockSubchannel3 ,
2318+ mockSubchannel2n2 , mockSubchannel3n2 );
23132319 Status error = Status .UNAUTHENTICATED .withDescription ("simulated failure" );
23142320
23152321 List <EquivalentAddressGroup > addrs =
@@ -2359,9 +2365,9 @@ public void happy_eyeballs_pick_pushes_index_over_end() {
23592365
23602366 // Try pushing after end with just picks
23612367 listeners [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 ));
23652371 loadBalancer .acceptResolvedAddresses (
23662372 ResolvedAddresses .newBuilder ().setAddresses (addrs ).setAttributes (affinity ).build ());
23672373 inOrder .verify (mockHelper ).updateBalancingState (eq (IDLE ), pickerCaptor .capture ());
@@ -2372,11 +2378,14 @@ public void happy_eyeballs_pick_pushes_index_over_end() {
23722378 }
23732379 assertEquals (IDLE , loadBalancer .getConcludedConnectivityState ());
23742380
2375- 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 ));
23782388 assertEquals (TRANSIENT_FAILURE , loadBalancer .getConcludedConnectivityState ());
2379-
23802389 }
23812390
23822391 @ Test
@@ -2571,9 +2580,22 @@ private static class FakeSocketAddress extends SocketAddress {
25712580
25722581 @ Override
25732582 public 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 }
25762594
2595+ @ Override
2596+ public int hashCode () {
2597+ return name .hashCode ();
2598+ }
25772599 }
25782600
25792601 private void forwardTimeByConnectionDelay () {
@@ -2631,15 +2653,26 @@ public void updateAddresses(List<EquivalentAddressGroup> addrs) {
26312653
26322654 @ Override
26332655 public void shutdown () {
2656+ listener .onSubchannelState (ConnectivityStateInfo .forNonError (SHUTDOWN ));
26342657 }
26352658
26362659 @ Override
26372660 public void requestConnection () {
2638- listener .onSubchannelState (ConnectivityStateInfo .forNonError (CONNECTING ));
2661+ }
2662+
2663+ @ Override
2664+ public String toString () {
2665+ return "FakeSubchannel@" + hashCode () + "(" + eags + ")" ;
26392666 }
26402667 }
26412668
26422669 private 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
26442677 public ManagedChannel createOobChannel (EquivalentAddressGroup eag , String authority ) {
26452678 return null ;
@@ -2672,16 +2705,17 @@ public void refreshNameResolution() {
26722705
26732706 @ Override
26742707 public 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+ }
0 commit comments