package liquibase.changelog;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
import liquibase.database.Database;
import liquibase.exception.DatabaseException;
import liquibase.executor.Executor;
import liquibase.executor.ExecutorService;
import org.junit.Test;
/**
* Tests for {@link liquibase.changelog.ChangeSet#execute(DatabaseChangeLog, Database)}
*/
public class ChangeSetExecuteTest {
private void trainToAcceptAnyNumberOfCommitsOrRollbacks(Database database) {
try {
database.commit();
expectLastCall().anyTimes();
database.rollback();
expectLastCall().anyTimes();
} catch (DatabaseException e) {
throw new RuntimeException(e);
}
}
private Database createMockDatabaseThatSupportsDdlInTran() {
Database database = createMock(Database.class);
expect(database.supportsDDLInTransaction()).andStubReturn(true);
expect(database.getAutoCommitMode()).andStubReturn(false);
return database;
}
private Database createMockDatabaseThatDoesNotSupportDdlInTran() {
Database database = createMock(Database.class);
expect(database.supportsDDLInTransaction()).andStubReturn(false);
expect(database.getAutoCommitMode()).andStubReturn(true);
return database;
}
private Executor createMockExecutor() {
Executor executor = createNiceMock(Executor.class);
replay(executor);
return executor;
}
private ChangeSet createTestChangeSet(boolean runInTransaction) {
return new ChangeSet("test-id", "test-author", false, false, "/test.xml", null, null, runInTransaction);
}
@Test
public void testMockDatabaseThatSupportsDdlInTran() {
Database database = createMockDatabaseThatSupportsDdlInTran();
replay(database);
assertTrue(database.supportsDDLInTransaction());
assertFalse(database.getAutoCommitMode());
}
@Test
public void testMockDatabaseThatDoesNotSupportDdlInTran() {
Database database = createMockDatabaseThatDoesNotSupportDdlInTran();
replay(database);
assertFalse(database.supportsDDLInTransaction());
assertTrue(database.getAutoCommitMode());
}
@Test
public void testExecuteForDatabaseThatSupportsDdlInTranWhenRunInTransactionIsTrue() throws Exception {
Database database = createMockDatabaseThatSupportsDdlInTran();
ExecutorService.getInstance().setExecutor(database, createMockExecutor());
checkOrder(database, true);
database.setAutoCommit(false); // before ChangeSet is run
checkOrder(database, false);
trainToAcceptAnyNumberOfCommitsOrRollbacks(database);
// no need to set back after ChangeSet is run because false is the auto-commit mode for
// databases that support DDL in transactions
replay(database);
ChangeSet changeSet = createTestChangeSet(true);
changeSet.execute(new DatabaseChangeLog(), database);
verify(database);
}
@Test
public void testExecuteForDatabaseThatSupportsDdlInTranWhenRunInTransactionIsFalse() throws Exception {
Database database = createMockDatabaseThatSupportsDdlInTran();
ExecutorService.getInstance().setExecutor(database, createMockExecutor());
checkOrder(database, true);
database.setAutoCommit(true); // before ChangeSet is run
checkOrder(database, false);
trainToAcceptAnyNumberOfCommitsOrRollbacks(database);
checkOrder(database, true);
database.setAutoCommit(false); // after ChangeSet is run
replay(database);
ChangeSet changeSet = createTestChangeSet(false);
changeSet.execute(new DatabaseChangeLog(), database);
verify(database);
}
@Test
public void testExecuteForDatabaseThatDoesNotSupportDdlInTranWhenRunInTransactionIsTrue() throws Exception {
Database database = createMockDatabaseThatDoesNotSupportDdlInTran();
ExecutorService.getInstance().setExecutor(database, createMockExecutor());
trainToAcceptAnyNumberOfCommitsOrRollbacks(database);
// database.setAutoCommit(boolean) should not be called
replay(database);
ChangeSet changeSet = createTestChangeSet(true);
changeSet.execute(new DatabaseChangeLog(), database);
verify(database);
}
@Test
public void testExecuteForDatabaseThatDoesNotSupportDdlInTranWhenRunInTransactionIsFalse() throws Exception {
Database database = createMockDatabaseThatDoesNotSupportDdlInTran();
ExecutorService.getInstance().setExecutor(database, createMockExecutor());
trainToAcceptAnyNumberOfCommitsOrRollbacks(database);
// database.setAutoCommit(boolean) should not be called
replay(database);
ChangeSet changeSet = createTestChangeSet(false);
changeSet.execute(new DatabaseChangeLog(), database);
verify(database);
}
}