@Test
public void testBasic() throws Exception
{

    RecordingListener recordingListener = new RecordingListener();
    TestRetryPolicy retryPolicy = new TestRetryPolicy();
    CircuitBreakingConnectionStateListener listener = new CircuitBreakingConnectionStateListener(dummyClient, recordingListener, retryPolicy, service);
    listener.stateChanged(dummyClient, ConnectionState.RECONNECTED);
    Assert.assertEquals(timing.takeFromQueue(recordingListener.stateChanges), ConnectionState.RECONNECTED);
    listener.stateChanged(dummyClient, ConnectionState.SUSPENDED);
    Assert.assertEquals(timing.takeFromQueue(recordingListener.stateChanges), ConnectionState.SUSPENDED);
    listener.stateChanged(dummyClient, ConnectionState.SUSPENDED);  // 2nd suspended is ignored
    Assert.assertTrue(recordingListener.stateChanges.isEmpty());
    listener.stateChanged(dummyClient, ConnectionState.LOST);
    Assert.assertEquals(timing.takeFromQueue(recordingListener.stateChanges), ConnectionState.LOST);
    synchronized(listener)  // don't let retry policy run while we're pushing state changes
    {
        listener.stateChanged(dummyClient, ConnectionState.READ_ONLY);   // all further events are ignored
        listener.stateChanged(dummyClient, ConnectionState.RECONNECTED);   // all further events are ignored
        listener.stateChanged(dummyClient, ConnectionState.SUSPENDED);   // all further events are ignored
        listener.stateChanged(dummyClient, ConnectionState.LOST);   // all further events are ignored
        listener.stateChanged(dummyClient, ConnectionState.SUSPENDED);   // all further events are ignored - this will be the last event
    }
    retryTiming.multiple(2).sleep();
    Assert.assertTrue(recordingListener.stateChanges.isEmpty());
    retryPolicy.isRetrying = false; // retry policy will return false
    Assert.assertEquals(timing.takeFromQueue(recordingListener.stateChanges), ConnectionState.SUSPENDED);
}