protected synchronized boolean ensureCoordinatorReady(final Timer timer) {
        return ensureCoordinatorReady(timer, false);
    }
@Test
    public void testCoordinatorDiscoveryExponentialBackoff() {
        // With exponential backoff, we will get retries at 10, 20, 40, 80, 100 ms (with jitter)
        int shortRetryBackoffMs = 10;
        int shortRetryBackoffMaxMs = 100;
        setupCoordinator(shortRetryBackoffMs, shortRetryBackoffMaxMs);

        for (int i = 0; i < 5; i++) {
            mockClient.prepareResponse(groupCoordinatorResponse(node, Errors.NONE));
        }

        // cut out the coordinator for 100 milliseconds to simulate a disconnect.
        // after backing off, we should be able to connect.
        mockClient.backoff(coordinatorNode, 100L);

        long initialTime = mockTime.milliseconds();
        coordinator.ensureCoordinatorReady(mockTime.timer(Long.MAX_VALUE));
        long endTime = mockTime.milliseconds();

        long lowerBoundBackoffMs = 0;
        long upperBoundBackoffMs = 0;
        for (int i = 0; i < 4; i++) {
            lowerBoundBackoffMs += (long) (shortRetryBackoffMs * Math.pow(CommonClientConfigs.RETRY_BACKOFF_EXP_BASE, i) * (1 - CommonClientConfigs.RETRY_BACKOFF_JITTER));
            upperBoundBackoffMs += (long) (shortRetryBackoffMs * Math.pow(CommonClientConfigs.RETRY_BACKOFF_EXP_BASE, i) * (1 + CommonClientConfigs.RETRY_BACKOFF_JITTER));
        }

        long timeElapsed = endTime - initialTime;
        assertTrue(timeElapsed >= lowerBoundBackoffMs);
        assertTrue(timeElapsed <= upperBoundBackoffMs + shortRetryBackoffMs);
    }