// Path: src/main/java/uk/sky/cqlmigrate/exception/CannotAcquireLockException.java
// public class CannotAcquireLockException extends LockException {
// 
//     public CannotAcquireLockException(String message) {
//         super(message);
//     }
// 
//     public CannotAcquireLockException(String message, Throwable cause) {
//         super(message, cause);
//     }
// }
// 
// Path: src/main/java/uk/sky/cqlmigrate/exception/CannotReleaseLockException.java
// public class CannotReleaseLockException extends LockException {
// 
//     public CannotReleaseLockException(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public CannotReleaseLockException(String message) {
//         super(message);
//     }
// }


import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.junit.Assert.fail;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import uk.sky.cqlmigrate.exception.CannotAcquireLockException;
import uk.sky.cqlmigrate.exception.CannotReleaseLockException;
import java.time.Duration;
        given(lockingMechanism.release(LOCK_CONFIG.getClientId())).willReturn(true);
        lock.lock();

        //when
        lock.unlock(false);

        //then
        verify(lockingMechanism).release(LOCK_CONFIG.getClientId());
    }

    @Test
    public void doesNotReleaseLockIfMigrationFailed() throws Throwable {
        //given
        given(lockingMechanism.acquire(LOCK_CONFIG.getClientId())).willReturn(true);
        lock.lock();

        //when
        lock.unlock(true);

        //then
        verify(lockingMechanism, never()).release(LOCK_CONFIG.getClientId());
    }

    @Test
    public void releasesLockOnLockIfUnlockOnFailureIsSetToTrue() throws Throwable {
        //given
        LockConfig lockConfig = LockConfig.builder()
                .withPollingInterval(Duration.ofMillis(POLLING_MILLIS))
                .withTimeout(Duration.ofMillis(TIMEOUT_MILLIS))
                .unlockOnFailure()
// Path: src/main/java/uk/sky/cqlmigrate/exception/CannotAcquireLockException.java
// public class CannotAcquireLockException extends LockException {
// 
//     public CannotAcquireLockException(String message) {
//         super(message);
//     }
// 
//     public CannotAcquireLockException(String message, Throwable cause) {
//         super(message, cause);
//     }
// }
// 
// Path: src/main/java/uk/sky/cqlmigrate/exception/CannotReleaseLockException.java
// public class CannotReleaseLockException extends LockException {
// 
//     public CannotReleaseLockException(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public CannotReleaseLockException(String message) {
//         super(message);
//     }
// }


// Path: src/test/java/uk/sky/cqlmigrate/LockTest.java
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.junit.Assert.fail;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import uk.sky.cqlmigrate.exception.CannotAcquireLockException;
import uk.sky.cqlmigrate.exception.CannotReleaseLockException;
import java.time.Duration;

        given(lockingMechanism.release(LOCK_CONFIG.getClientId())).willReturn(true);
        lock.lock();

        //when
        lock.unlock(false);

        //then
        verify(lockingMechanism).release(LOCK_CONFIG.getClientId());
    }

    @Test
    public void doesNotReleaseLockIfMigrationFailed() throws Throwable {
        //given
        given(lockingMechanism.acquire(LOCK_CONFIG.getClientId())).willReturn(true);
        lock.lock();

        //when
        lock.unlock(true);

        //then
        verify(lockingMechanism, never()).release(LOCK_CONFIG.getClientId());
    }

    @Test
    public void releasesLockOnLockIfUnlockOnFailureIsSetToTrue() throws Throwable {
        //given
        LockConfig lockConfig = LockConfig.builder()
                .withPollingInterval(Duration.ofMillis(POLLING_MILLIS))
                .withTimeout(Duration.ofMillis(TIMEOUT_MILLIS))
                .unlockOnFailure()
                .build();