Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make baseline() idempotent even after applying migrations #1345

Merged
merged 3 commits into from Jan 31, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -112,9 +112,6 @@ public Object doInTransaction() throws SQLException {
new TransactionTemplate(connection).execute(new TransactionCallback<Void>() {
public Void doInTransaction() {
dbSupport.changeCurrentSchemaTo(schema);
if (metaDataTable.hasAppliedMigrations()) {
throw new FlywayException("Unable to baseline metadata table " + metaDataTable + " as it already contains migrations");
}
if (metaDataTable.hasBaselineMarker()) {
AppliedMigration baselineMarker = metaDataTable.getBaselineMarker();
if (baselineVersion.equals(baselineMarker.getVersion())
Expand All @@ -131,6 +128,9 @@ public Void doInTransaction() {
if (metaDataTable.hasSchemasMarker() && baselineVersion.equals(MigrationVersion.fromVersion("0"))) {
throw new FlywayException("Unable to baseline metadata table " + metaDataTable + " with version 0 as this version was used for schema creation");
}
if (metaDataTable.hasAppliedMigrations()) {
throw new FlywayException("Unable to baseline metadata table " + metaDataTable + " as it already contains migrations");
}
metaDataTable.addBaselineMarker(baselineVersion, baselineDescription);

return null;
Expand Down
@@ -0,0 +1,165 @@
package org.flywaydb.core.internal.command;

import java.sql.Connection;
import org.flywaydb.core.api.FlywayException;
import org.flywaydb.core.api.MigrationType;
import org.flywaydb.core.api.MigrationVersion;
import org.flywaydb.core.api.callback.FlywayCallback;
import org.flywaydb.core.internal.dbsupport.DbSupport;
import org.flywaydb.core.internal.dbsupport.Schema;
import org.flywaydb.core.internal.metadatatable.AppliedMigration;
import org.flywaydb.core.internal.metadatatable.MetaDataTable;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Mockito;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;


public class DbBaselineTest {

private static final MigrationVersion TEST_BASELINE_VERSION = MigrationVersion.fromVersion("2.0.0");
private static final String TEST_BASELINE_DESCRIPTION = "test baseline";

private Connection connection;
private DbSupport dbSupport;
private Schema schema;
private FlywayCallback testCallback;
private FlywayCallback[] callbacks;
private MetaDataTable metaDataTable;
private DbBaseline testBaseline;

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Before
public void before() {
this.connection = mock(Connection.class);
this.dbSupport = mock(DbSupport.class);
this.schema = mock(Schema.class);
testCallback = mock(FlywayCallback.class);
callbacks = new FlywayCallback[] { this.testCallback };
this.metaDataTable = mock(MetaDataTable.class);

this.testBaseline = createTestBaselinie(TEST_BASELINE_VERSION);
}

@Test
public void newBaseline() {
// arrange
when(this.metaDataTable.hasBaselineMarker()).thenReturn(false);

// act
this.testBaseline.baseline();

// assert
verify(this.metaDataTable).addBaselineMarker(TEST_BASELINE_VERSION, TEST_BASELINE_DESCRIPTION);
verify(this.testCallback).beforeBaseline(this.connection);
verify(this.testCallback).afterBaseline(this.connection);
}

@Test
public void newBaselineWithMigrations() {
// arrange
when(this.metaDataTable.hasBaselineMarker()).thenReturn(false);
when(this.metaDataTable.hasAppliedMigrations()).thenReturn(true);

// assert
this.expectedException.expect(FlywayException.class);
this.expectedException.expectMessage("contains migrations");

// act
this.testBaseline.baseline();
}

@Test
public void sameBaselineMarkerPresentWithoutMigrations() {
// arrange
AppliedMigration baseline = new AppliedMigration(TEST_BASELINE_VERSION, TEST_BASELINE_DESCRIPTION, MigrationType.BASELINE, "V2.0.0__test-migration.sql", 12345, 100, true);
when(this.metaDataTable.hasBaselineMarker()).thenReturn(true);
when(this.metaDataTable.getBaselineMarker()).thenReturn(baseline);
when(this.metaDataTable.hasAppliedMigrations()).thenReturn(false);

// act
this.testBaseline.baseline();

// assert
verify(metaDataTable, never()).addBaselineMarker(Mockito.<MigrationVersion>anyObject(), anyString());
}

@Test
public void sameBaselineMarkerPresentWithMigrations() {
// arrange
AppliedMigration baseline = new AppliedMigration(TEST_BASELINE_VERSION, TEST_BASELINE_DESCRIPTION, MigrationType.BASELINE, "V2.0.0__test-migration.sql", 12345, 100, true);
when(this.metaDataTable.hasBaselineMarker()).thenReturn(true);
when(this.metaDataTable.getBaselineMarker()).thenReturn(baseline);
when(this.metaDataTable.hasAppliedMigrations()).thenReturn(true);

// act
this.testBaseline.baseline();

// assert
verify(metaDataTable, never()).addBaselineMarker(Mockito.<MigrationVersion>anyObject(), anyString());
}

@Test
public void differentBaselineMarkerVersionPresent() {
// arrange
MigrationVersion baselineVersion = MigrationVersion.fromVersion("3.0.0");
AppliedMigration baseline = new AppliedMigration(baselineVersion, TEST_BASELINE_DESCRIPTION, MigrationType.BASELINE, "V2.0.0__test-migration.sql", 12345, 100, true);
when(this.metaDataTable.hasBaselineMarker()).thenReturn(true);
when(this.metaDataTable.getBaselineMarker()).thenReturn(baseline);

// assert
this.expectedException.expect(FlywayException.class);
this.expectedException.expectMessage(TEST_BASELINE_VERSION.toString());
this.expectedException.expectMessage(TEST_BASELINE_DESCRIPTION.toString());
this.expectedException.expectMessage(baselineVersion.toString());

// act
this.testBaseline.baseline();
}

@Test
public void differentBaselineMarkerDescriptionPresent() {
// arrange
String baselineDescription = "Differen description";
AppliedMigration baseline = new AppliedMigration(TEST_BASELINE_VERSION, baselineDescription, MigrationType.BASELINE, "V2.0.0__test-migration.sql", 12345, 100, true);
when(this.metaDataTable.hasBaselineMarker()).thenReturn(true);
when(this.metaDataTable.getBaselineMarker()).thenReturn(baseline);

// assert
this.expectedException.expect(FlywayException.class);
this.expectedException.expectMessage(TEST_BASELINE_VERSION.toString());
this.expectedException.expectMessage(TEST_BASELINE_DESCRIPTION.toString());
this.expectedException.expectMessage(baselineDescription);

// act
this.testBaseline.baseline();
}


@Test
public void schemaMarkerPresentAndBaselineVersionZero() {
// arrange
DbBaseline versionZeroBaseline = createTestBaselinie(MigrationVersion.fromVersion("0"));
when(this.metaDataTable.hasSchemasMarker()).thenReturn(true);

// assert
this.expectedException.expect(FlywayException.class);
this.expectedException.expectMessage("used for schema creation");

// act
versionZeroBaseline.baseline();
}

private DbBaseline createTestBaselinie(MigrationVersion version) {
return new DbBaseline(connection, dbSupport, metaDataTable, schema, version, TEST_BASELINE_DESCRIPTION, callbacks);
}

}