88import java .net .Proxy ;
99import java .net .URI ;
1010import java .net .URISyntaxException ;
11+ import java .util .concurrent .ScheduledExecutorService ;
1112import java .util .concurrent .ScheduledThreadPoolExecutor ;
13+ import java .util .concurrent .TimeUnit ;
1214
1315import javax .net .ssl .SSLException ;
1416
2628import com .pusher .client .connection .ConnectionStateChange ;
2729import com .pusher .client .util .DoNothingExecutor ;
2830import com .pusher .client .util .Factory ;
31+ import com .pusher .client .util .SynchronousExecutor ;
2932
3033@ RunWith (MockitoJUnitRunner .class )
3134public class WebSocketConnectionTest {
@@ -49,6 +52,8 @@ public class WebSocketConnectionTest {
4952 private ConnectionEventListener mockEventListener ;
5053 @ Mock
5154 private Factory factory ;
55+ @ Mock
56+ private ScheduledExecutorService scheduledExecutorService ;
5257
5358 private WebSocketConnection connection ;
5459
@@ -360,26 +365,47 @@ public void stateIsReconnectingAfterTryingToConnectForTheFirstTime() throws Inte
360365 assertEquals (ConnectionState .RECONNECTING , connection .getState ());
361366 }
362367
363- // TODO: leaving the following tests commented out just for reference. The lib needs to be rearchitected before we can hope to get any of these in
364- // @Test
365- // public void reconnectingLogicActuallyBeingCalled(){
366- // fail("not implemented");
367- // }
368- //
369- // @Test
370- // public void retryMaximumNumberOfTimes(){
371- // fail("not implemented");
372- // }
373- //
374- // @Test
375- // public void disconnectAfterTooManyRetries(){
376- // fail("not implemented");
377- // }
378- //
379- // @Test
380- // public void retryWithTimeout(){
381- // fail("not implemented");
382- // }
368+ @ Test
369+ @ SuppressWarnings ("rawtypes" )
370+ public void testStopsReconnectingAfterMaxReconnectionAttemptsIsReached () throws URISyntaxException , InterruptedException , SSLException {
371+ when (factory .getTimers ()).thenReturn (scheduledExecutorService );
372+ // Run the reconnect functionality synchronously
373+ doAnswer (new Answer () {
374+ @ Override
375+ public Object answer (InvocationOnMock invocation ) throws Throwable {
376+ final Runnable r = (Runnable ) invocation .getArguments ()[0 ];
377+ r .run ();
378+ return null ;
379+ }
380+ }).when (scheduledExecutorService ).schedule (any (Runnable .class ), any (Long .class ), any (TimeUnit .class ));
381+
382+ // Reconnect a single time (maxReconnectionAttempts = 1)
383+ connection = new WebSocketConnection (URL , ACTIVITY_TIMEOUT , PONG_TIMEOUT , 1 , MAX_GAP , PROXY , factory );
384+
385+ connection .connect ();
386+
387+ // After the first close, we expect a reconnect
388+ connection .onClose (500 , "reason" , true );
389+ assertEquals (ConnectionState .CONNECTING , connection .getState ());
390+
391+ // It should give up on the second attempt
392+ connection .onClose (500 , "reason" , true );
393+ assertEquals (ConnectionState .DISCONNECTED , connection .getState ());
394+
395+ // Test that behavior is the same after `connect()` is called
396+ // This guards against a bug fixed in https://github.com/pusher/pusher-websocket-java/pull/201
397+ // where the number of retries was not reset after calling `connect()`.
398+
399+ connection .connect ();
400+
401+ // After the first close, we expect a reconnect
402+ connection .onClose (500 , "reason" , true );
403+ assertEquals (ConnectionState .CONNECTING , connection .getState ());
404+
405+ // It should give up on the second attempt
406+ connection .onClose (500 , "reason" , true );
407+ assertEquals (ConnectionState .DISCONNECTED , connection .getState ());
408+ }
383409
384410 /* end of tests */
385411
0 commit comments