// Path: cassandra-migration/src/main/java/org/cognitor/cassandra/migration/MigrationTask.java
// public class MigrationTask {
//     private static final Logger LOGGER = getLogger(MigrationTask.class);
// 
//     private final Database database;
//     private final MigrationRepository repository;
//     private final boolean withConsensus;
// 
//     /**
//      * Creates a migration task that uses the given database and repository and no consensus
//      * protocol enabled.
//      *
//      * @param database   the database that should be migrated
//      * @param repository the repository that contains the migration scripts
//      */
//     public MigrationTask(Database database, MigrationRepository repository) {
//         this(database, repository, false);
//     }
// 
//     /**
//      * Creates a migration task that uses the given database and repository.
//      *
//      * @param database      the database that should be migrated
//      * @param repository    the repository that contains the migration scripts
//      * @param withConsensus if the migration should be handled by a single process at once, using LWT based leader election
//      */
//     public MigrationTask(Database database, MigrationRepository repository, boolean withConsensus) {
//         this.database = notNull(database, "database");
//         this.repository = notNull(repository, "repository");
//         this.withConsensus = withConsensus;
//     }
// 
//     /**
//      * Start the actual migration. Take the version of the database, get all required migrations and execute them or do
//      * nothing if the DB is already up to date.
//      * <p>
//      * At the end the underlying database instance is closed.
//      *
//      * @throws MigrationException if a migration fails
//      */
//     public void migrate() {
//         if (databaseIsUpToDate()) {
//             LOGGER.info(format("Keyspace %s is already up to date at version %d", database.getKeyspaceName(),
//                     database.getVersion()));
//             database.close();
//             return;
//         }
// 
//         try {
//             if (!instanceHasLead()) {
//                 return;
//             }
//             if (!databaseIsUpToDate()) {
//                 List<DbMigration> migrations = repository.getMigrationsSinceVersion(database.getVersion());
//                 migrations.forEach(database::execute);
//                 LOGGER.info(format("Migrated keyspace %s to version %d", database.getKeyspaceName(),
//                         database.getVersion()));
//             }
//         } finally {
//             if (withConsensus) {
//                 database.removeLeadOnMigrations();
//             }
//             database.close();
//         }
//     }
// 
//     private boolean instanceHasLead() {
//         return !withConsensus || database.takeLeadOnMigrations(repository.getLatestVersion());
//     }
// 
//     private boolean databaseIsUpToDate() {
//         return database.getVersion() >= repository.getLatestVersion();
//     }
// }
// 
// Path: cassandra-migration-spring-boot-starter/src/main/java/org/cognitor/cassandra/migration/spring/CassandraMigrationAutoConfiguration.java
// public static final String CQL_SESSION_BEAN_NAME = "cassandraMigrationCqlSession";


import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.CqlSessionBuilder;
import com.datastax.oss.driver.api.core.config.DefaultDriverOption;
import com.datastax.oss.driver.api.core.config.DriverConfigLoader;
import com.datastax.oss.driver.api.core.cql.Row;
import org.cognitor.cassandra.migration.MigrationTask;
import org.hamcrest.CoreMatchers;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.net.InetSocketAddress;
import java.time.Duration;
import java.util.List;
import static org.cognitor.cassandra.migration.spring.CassandraMigrationAutoConfiguration.CQL_SESSION_BEAN_NAME;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
                new AnnotationConfigApplicationContext();
        TestPropertyValues testValues = TestPropertyValues.of("cassandra.migration.keyspace-name:" + KEYSPACE)
                .and("cassandra.migration.table-prefix:test");
        testValues.applyTo(context);
        context.register(ClusterConfig.class, CassandraMigrationAutoConfiguration.class);
        context.refresh();

        // WHEN
        context.getBean(MigrationTask.class);

        // THEN
        CqlSession session = createSession();
        List<Row> rows = session.execute("SELECT * FROM " + KEYSPACE + ".test_schema_migration").all();
        assertThat(rows.size(), is(equalTo(1)));
        Row migration = rows.get(0);
        assertThat(migration.getBoolean("applied_successful"), is(true));
        assertThat(migration.getInstant("executed_at"), is(not(nullValue())));
        assertThat(migration.getString("script_name"), is(CoreMatchers.equalTo("001_create_person_table.cql")));
        assertThat(migration.getString("script"), startsWith("CREATE TABLE"));
    }

    private CqlSession createSession() {
        return new ClusterConfig().session();
    }

    @Configuration
    static class ClusterConfig {
        private static final String CASSANDRA_HOST = "127.0.0.1";
        private static final int REQUEST_TIMEOUT_IN_SECONDS = 30;

// Path: cassandra-migration/src/main/java/org/cognitor/cassandra/migration/MigrationTask.java
// public class MigrationTask {
//     private static final Logger LOGGER = getLogger(MigrationTask.class);
// 
//     private final Database database;
//     private final MigrationRepository repository;
//     private final boolean withConsensus;
// 
//     /**
//      * Creates a migration task that uses the given database and repository and no consensus
//      * protocol enabled.
//      *
//      * @param database   the database that should be migrated
//      * @param repository the repository that contains the migration scripts
//      */
//     public MigrationTask(Database database, MigrationRepository repository) {
//         this(database, repository, false);
//     }
// 
//     /**
//      * Creates a migration task that uses the given database and repository.
//      *
//      * @param database      the database that should be migrated
//      * @param repository    the repository that contains the migration scripts
//      * @param withConsensus if the migration should be handled by a single process at once, using LWT based leader election
//      */
//     public MigrationTask(Database database, MigrationRepository repository, boolean withConsensus) {
//         this.database = notNull(database, "database");
//         this.repository = notNull(repository, "repository");
//         this.withConsensus = withConsensus;
//     }
// 
//     /**
//      * Start the actual migration. Take the version of the database, get all required migrations and execute them or do
//      * nothing if the DB is already up to date.
//      * <p>
//      * At the end the underlying database instance is closed.
//      *
//      * @throws MigrationException if a migration fails
//      */
//     public void migrate() {
//         if (databaseIsUpToDate()) {
//             LOGGER.info(format("Keyspace %s is already up to date at version %d", database.getKeyspaceName(),
//                     database.getVersion()));
//             database.close();
//             return;
//         }
// 
//         try {
//             if (!instanceHasLead()) {
//                 return;
//             }
//             if (!databaseIsUpToDate()) {
//                 List<DbMigration> migrations = repository.getMigrationsSinceVersion(database.getVersion());
//                 migrations.forEach(database::execute);
//                 LOGGER.info(format("Migrated keyspace %s to version %d", database.getKeyspaceName(),
//                         database.getVersion()));
//             }
//         } finally {
//             if (withConsensus) {
//                 database.removeLeadOnMigrations();
//             }
//             database.close();
//         }
//     }
// 
//     private boolean instanceHasLead() {
//         return !withConsensus || database.takeLeadOnMigrations(repository.getLatestVersion());
//     }
// 
//     private boolean databaseIsUpToDate() {
//         return database.getVersion() >= repository.getLatestVersion();
//     }
// }
// 
// Path: cassandra-migration-spring-boot-starter/src/main/java/org/cognitor/cassandra/migration/spring/CassandraMigrationAutoConfiguration.java
// public static final String CQL_SESSION_BEAN_NAME = "cassandraMigrationCqlSession";


// Path: cassandra-migration-spring-boot-starter/src/test/java/org/cognitor/cassandra/migration/spring/CassandraMigrationAutoConfigurationTest.java
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.CqlSessionBuilder;
import com.datastax.oss.driver.api.core.config.DefaultDriverOption;
import com.datastax.oss.driver.api.core.config.DriverConfigLoader;
import com.datastax.oss.driver.api.core.cql.Row;
import org.cognitor.cassandra.migration.MigrationTask;
import org.hamcrest.CoreMatchers;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.net.InetSocketAddress;
import java.time.Duration;
import java.util.List;
import static org.cognitor.cassandra.migration.spring.CassandraMigrationAutoConfiguration.CQL_SESSION_BEAN_NAME;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

                new AnnotationConfigApplicationContext();
        TestPropertyValues testValues = TestPropertyValues.of("cassandra.migration.keyspace-name:" + KEYSPACE)
                .and("cassandra.migration.table-prefix:test");
        testValues.applyTo(context);
        context.register(ClusterConfig.class, CassandraMigrationAutoConfiguration.class);
        context.refresh();

        // WHEN
        context.getBean(MigrationTask.class);

        // THEN
        CqlSession session = createSession();
        List<Row> rows = session.execute("SELECT * FROM " + KEYSPACE + ".test_schema_migration").all();
        assertThat(rows.size(), is(equalTo(1)));
        Row migration = rows.get(0);
        assertThat(migration.getBoolean("applied_successful"), is(true));
        assertThat(migration.getInstant("executed_at"), is(not(nullValue())));
        assertThat(migration.getString("script_name"), is(CoreMatchers.equalTo("001_create_person_table.cql")));
        assertThat(migration.getString("script"), startsWith("CREATE TABLE"));
    }

    private CqlSession createSession() {
        return new ClusterConfig().session();
    }

    @Configuration
    static class ClusterConfig {
        private static final String CASSANDRA_HOST = "127.0.0.1";
        private static final int REQUEST_TIMEOUT_IN_SECONDS = 30;

        @Bean(name = CQL_SESSION_BEAN_NAME)