// Path: src/main/java/uk/sky/cqlmigrate/exception/ClusterUnhealthyException.java
// public class ClusterUnhealthyException extends RuntimeException {
//     public ClusterUnhealthyException(String message) {
//         super(message);
//     }
// }
// 
// Path: src/test/java/uk/sky/cqlmigrate/util/PortScavenger.java
// public class PortScavenger {
// 
//     public static int getFreePort() {
//         ServerSocket socket = null;
//         try {
//             socket = new ServerSocket(0);
//             socket.setReuseAddress(true);
//             int port = socket.getLocalPort();
//             closeSocket(socket);
//             return port;
//         } catch (IOException ignored) {
//         } finally {
//             closeSocket(socket);
//         }
//         throw new IllegalStateException("Could not find a free TCP/IP port to start embedded Jetty HTTP Server on");
// 
//     }
// 
//     private static void closeSocket(ServerSocket socket) {
//         if (socket != null) {
//             try {
//                 socket.close();
//             } catch (IOException ignored) {
//             }
//         }
//     }
// }


import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.simulacron.common.cluster.ClusterSpec;
import com.datastax.oss.simulacron.common.cluster.DataCenterSpec;
import com.datastax.oss.simulacron.server.BoundCluster;
import com.datastax.oss.simulacron.server.RejectScope;
import com.datastax.oss.simulacron.server.Server;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import uk.sky.cqlmigrate.exception.ClusterUnhealthyException;
import uk.sky.cqlmigrate.util.PortScavenger;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.UUID;
import static com.datastax.oss.simulacron.common.stubbing.CloseType.DISCONNECT;
import static com.datastax.oss.simulacron.common.stubbing.PrimeDsl.rows;
import static com.datastax.oss.simulacron.common.stubbing.PrimeDsl.when;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.awaitility.Awaitility.await;

        bCluster.prime(when("select cluster_name from system.local where key = 'local'")
                .then(rows().row("cluster_name", "0").build()));

        realCluster = CqlSession.builder()
                .addContactPoint(new InetSocketAddress(Inet4Address.getByAddress(new byte[]{127, 0, 0, 1}), defaultStartingPort))
                .withLocalDatacenter(dc.getName())
                .build();
        clusterHealth = new ClusterHealth(realCluster);
    }

    @After
    public void tearDown() {
        realCluster.close();
    }

    @Test
    public void shouldThrowExceptionIfHostIsDown() {
        //given
        bCluster.node(0).closeConnections(DISCONNECT);
        bCluster.node(0).rejectConnections(0, RejectScope.UNBIND);

        await().pollInterval(500, MILLISECONDS)
                .atMost(5, SECONDS)
                .untilAsserted(() -> {
                    //when
                    Throwable throwable = catchThrowable(clusterHealth::check);

                    //then
                    assertThat(throwable).isNotNull();
// Path: src/main/java/uk/sky/cqlmigrate/exception/ClusterUnhealthyException.java
// public class ClusterUnhealthyException extends RuntimeException {
//     public ClusterUnhealthyException(String message) {
//         super(message);
//     }
// }
// 
// Path: src/test/java/uk/sky/cqlmigrate/util/PortScavenger.java
// public class PortScavenger {
// 
//     public static int getFreePort() {
//         ServerSocket socket = null;
//         try {
//             socket = new ServerSocket(0);
//             socket.setReuseAddress(true);
//             int port = socket.getLocalPort();
//             closeSocket(socket);
//             return port;
//         } catch (IOException ignored) {
//         } finally {
//             closeSocket(socket);
//         }
//         throw new IllegalStateException("Could not find a free TCP/IP port to start embedded Jetty HTTP Server on");
// 
//     }
// 
//     private static void closeSocket(ServerSocket socket) {
//         if (socket != null) {
//             try {
//                 socket.close();
//             } catch (IOException ignored) {
//             }
//         }
//     }
// }


// Path: src/test/java/uk/sky/cqlmigrate/ClusterHealthTest.java
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.simulacron.common.cluster.ClusterSpec;
import com.datastax.oss.simulacron.common.cluster.DataCenterSpec;
import com.datastax.oss.simulacron.server.BoundCluster;
import com.datastax.oss.simulacron.server.RejectScope;
import com.datastax.oss.simulacron.server.Server;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import uk.sky.cqlmigrate.exception.ClusterUnhealthyException;
import uk.sky.cqlmigrate.util.PortScavenger;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.UUID;
import static com.datastax.oss.simulacron.common.stubbing.CloseType.DISCONNECT;
import static com.datastax.oss.simulacron.common.stubbing.PrimeDsl.rows;
import static com.datastax.oss.simulacron.common.stubbing.PrimeDsl.when;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.awaitility.Awaitility.await;


        bCluster.prime(when("select cluster_name from system.local where key = 'local'")
                .then(rows().row("cluster_name", "0").build()));

        realCluster = CqlSession.builder()
                .addContactPoint(new InetSocketAddress(Inet4Address.getByAddress(new byte[]{127, 0, 0, 1}), defaultStartingPort))
                .withLocalDatacenter(dc.getName())
                .build();
        clusterHealth = new ClusterHealth(realCluster);
    }

    @After
    public void tearDown() {
        realCluster.close();
    }

    @Test
    public void shouldThrowExceptionIfHostIsDown() {
        //given
        bCluster.node(0).closeConnections(DISCONNECT);
        bCluster.node(0).rejectConnections(0, RejectScope.UNBIND);

        await().pollInterval(500, MILLISECONDS)
                .atMost(5, SECONDS)
                .untilAsserted(() -> {
                    //when
                    Throwable throwable = catchThrowable(clusterHealth::check);

                    //then
                    assertThat(throwable).isNotNull();
                    assertThat(throwable).isInstanceOf(ClusterUnhealthyException.class);