From 5801183df4cefa028241606f029c4576c6f26a6b Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=A9bastien=20Lesaint?= Date: Thu, 15 Dec 2016 15:19:48 +0100 Subject: [PATCH] SONAR-8445 drop field DatabaseVersion.LAST_VERSION replace usages of this field by either MigrationSteps.getMaxMigrationNumber() or DatabaseVersion.getStatus() also, change return type of DatabaseVersion.getVersion from int to Optional MigrationStep configuration is now avaiable at level2, in both web and CE container (because it is used by DatabaseVersion class) --- .../container/ComputeEngineContainerImpl.java | 4 +- .../ComputeEngineContainerImplTest.java | 3 +- ...java => MigrationConfigurationModule.java} | 18 +++-- .../db/migration/MigrationEngineModule.java | 15 +--- .../history/MigrationHistoryImpl.java | 4 -- .../db/migration/version/DatabaseVersion.java | 67 +++++++---------- ... => MigrationConfigurationModuleTest.java} | 12 ++-- .../migration/MigrationEngineModuleTest.java | 2 +- .../version/DatabaseVersionTest.java | 68 ++++++++++-------- .../platform/DatabaseServerCompatibility.java | 5 +- .../platform/DefaultServerUpgradeStatus.java | 16 +++-- .../platformlevel/PlatformLevel2.java | 17 ++++- .../platformlevel/PlatformLevelSafeMode.java | 4 +- .../platform/ws/DbMigrationStatusAction.java | 10 +-- .../server/platform/ws/MigrateDbAction.java | 8 ++- .../java/org/sonar/server/ui/JRubyFacade.java | 15 ++-- .../DatabaseServerCompatibilityTest.java | 5 +- .../DefaultServerUpgradeStatusTest.java | 52 ++++++++------ .../monitoring/DatabaseMonitorTest.java | 11 ++- .../platformlevel/PlatformLevel2Test.java | 8 +-- .../ws/DbMigrationStatusActionTest.java | 72 ++++++++++++------- .../platform/ws/MigrateDbActionTest.java | 64 +++++++++++------ 22 files changed, 276 insertions(+), 204 deletions(-) rename server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/{version/DbVersionModule.java => MigrationConfigurationModule.java} (73%) rename server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/{version/DbVersionModuleTest.java => MigrationConfigurationModuleTest.java} (80%) diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java index 0b13b6fc832..2b82ec5d194 100644 --- a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java +++ b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java @@ -63,7 +63,6 @@ import org.sonar.db.DatabaseChecker; import org.sonar.db.DbClient; import org.sonar.db.DefaultDatabase; import org.sonar.db.purge.PurgeProfiler; -import org.sonar.server.platform.db.migration.version.DatabaseVersion; import org.sonar.process.Props; import org.sonar.process.logging.LogbackHelper; import org.sonar.server.component.ComponentCleanerService; @@ -114,6 +113,8 @@ import org.sonar.server.platform.TempFolderProvider; import org.sonar.server.platform.UrlSettings; import org.sonar.server.platform.cluster.ClusterImpl; import org.sonar.server.platform.cluster.ClusterProperties; +import org.sonar.server.platform.db.migration.MigrationConfigurationModule; +import org.sonar.server.platform.db.migration.version.DatabaseVersion; import org.sonar.server.plugins.InstalledPluginReferentialFactory; import org.sonar.server.plugins.ServerExtensionInstaller; import org.sonar.server.plugins.privileged.PrivilegedPluginsBootstraper; @@ -251,6 +252,7 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer { private static Object[] level2Components() { return new Object[] { + MigrationConfigurationModule.class, DatabaseVersion.class, DatabaseServerCompatibility.class, diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java index 6b915dd5648..87e2eb8a969 100644 --- a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java +++ b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java @@ -101,7 +101,8 @@ public class ComputeEngineContainerImplTest { ); assertThat(picoContainer.getParent().getParent().getComponentAdapters()).hasSize( CONTAINER_ITSELF - + 16 // level 2 + + 9 // MigrationConfigurationModule + + 17 // level 2 ); assertThat(picoContainer.getParent().getParent().getParent().getComponentAdapters()).hasSize( COMPONENTS_IN_LEVEL_1_AT_CONSTRUCTION diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/DbVersionModule.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java similarity index 73% rename from server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/DbVersionModule.java rename to server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java index 0de137980aa..dc41da42ae7 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/DbVersionModule.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java @@ -17,9 +17,12 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.platform.db.migration.version; +package org.sonar.server.platform.db.migration; import org.sonar.core.platform.Module; +import org.sonar.server.platform.db.migration.history.MigrationHistoryImpl; +import org.sonar.server.platform.db.migration.step.MigrationStepRegistryImpl; +import org.sonar.server.platform.db.migration.step.MigrationStepsProvider; import org.sonar.server.platform.db.migration.version.v56.DbVersion56; import org.sonar.server.platform.db.migration.version.v561.DbVersion561; import org.sonar.server.platform.db.migration.version.v60.DbVersion60; @@ -27,16 +30,23 @@ import org.sonar.server.platform.db.migration.version.v61.DbVersion61; import org.sonar.server.platform.db.migration.version.v62.DbVersion62; import org.sonar.server.platform.db.migration.version.v63.DbVersion63; -public class DbVersionModule extends Module { +public class MigrationConfigurationModule extends Module { @Override protected void configureModule() { add( + // DbVersion implementations DbVersion56.class, DbVersion561.class, DbVersion60.class, DbVersion61.class, DbVersion62.class, - DbVersion63.class); - } + DbVersion63.class, + + // migration steps + MigrationStepRegistryImpl.class, + new MigrationStepsProvider(), + // history + MigrationHistoryImpl.class); + } } diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationEngineModule.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationEngineModule.java index 69ca3930f5f..620161f93f9 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationEngineModule.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationEngineModule.java @@ -22,27 +22,14 @@ package org.sonar.server.platform.db.migration; import org.sonar.core.platform.Module; import org.sonar.server.platform.db.migration.engine.MigrationContainerPopulatorImpl; import org.sonar.server.platform.db.migration.engine.MigrationEngineImpl; -import org.sonar.server.platform.db.migration.history.MigrationHistoryImpl; -import org.sonar.server.platform.db.migration.step.MigrationStepRegistryImpl; -import org.sonar.server.platform.db.migration.step.MigrationStepsProvider; /** - * Defines the components for the migration engine. This does not include the - * {@link org.sonar.server.platform.db.migration.version.DbVersion} classes which are bundled together in - * {@link org.sonar.server.platform.db.migration.version.DbVersionModule}. + * Defines the components for the migration engine. */ public class MigrationEngineModule extends Module { @Override protected void configureModule() { add( - // migration steps - MigrationStepRegistryImpl.class, - new MigrationStepsProvider(), - - // history - MigrationHistoryImpl.class, - - // engine MigrationContainerPopulatorImpl.class, MigrationEngineImpl.class); } diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImpl.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImpl.java index b1fc36497ad..155cf150eb5 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImpl.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImpl.java @@ -30,13 +30,9 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.schemamigration.SchemaMigrationMapper; import org.sonar.server.platform.db.migration.step.RegisteredMigrationStep; -import org.sonar.server.platform.db.migration.version.DatabaseVersion; import static com.google.common.base.Preconditions.checkState; -/** - * TODO make {@link DatabaseVersion} use this class - */ public class MigrationHistoryImpl implements MigrationHistory { private final DbClient dbClient; diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/DatabaseVersion.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/DatabaseVersion.java index cfe8a89f23e..a3ffa84f870 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/DatabaseVersion.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/DatabaseVersion.java @@ -19,63 +19,50 @@ */ package org.sonar.server.platform.db.migration.version; -import com.google.common.annotations.VisibleForTesting; -import java.util.Collections; -import java.util.List; -import javax.annotation.Nullable; -import org.sonar.db.DatabaseUtils; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; +import java.util.Optional; +import org.sonar.server.platform.db.migration.history.MigrationHistory; +import org.sonar.server.platform.db.migration.step.MigrationSteps; public class DatabaseVersion { - public static final int LAST_VERSION = 1_502; - /** * The minimum supported version which can be upgraded. Lower * versions must be previously upgraded to LTS version. * Note that the value can't be less than current LTS version. */ - public static final int MIN_UPGRADE_VERSION = 1_152; + public static final long MIN_UPGRADE_VERSION = 1_152; - private final DbClient dbClient; + private final MigrationSteps migrationSteps; + private final MigrationHistory migrationHistory; - public DatabaseVersion(DbClient dbClient) { - this.dbClient = dbClient; - } - - @VisibleForTesting - static Status getStatus(@Nullable Integer currentVersion, int lastVersion) { - Status status = Status.FRESH_INSTALL; - if (currentVersion != null) { - if (currentVersion == lastVersion) { - status = Status.UP_TO_DATE; - } else if (currentVersion > lastVersion) { - status = Status.REQUIRES_DOWNGRADE; - } else { - status = Status.REQUIRES_UPGRADE; - } - } - return status; + public DatabaseVersion(MigrationSteps migrationSteps, MigrationHistory migrationHistory) { + this.migrationSteps = migrationSteps; + this.migrationHistory = migrationHistory; } public Status getStatus() { - return getStatus(getVersion(), LAST_VERSION); + return getStatus(migrationHistory.getLastMigrationNumber(), migrationSteps.getMaxMigrationNumber()); } - public Integer getVersion() { - try (DbSession dbSession = dbClient.openSession(false)) { - if (!DatabaseUtils.tableExists("SCHEMA_MIGRATIONS", dbSession.getConnection())) { - return null; - } + /** + * Convenience method to retrieve the value of {@link MigrationHistory#getLastMigrationNumber()}. + */ + public Optional getVersion() { + return migrationHistory.getLastMigrationNumber(); + } - List versions = dbClient.schemaMigrationDao().selectVersions(dbSession); - if (!versions.isEmpty()) { - Collections.sort(versions); - return versions.get(versions.size() - 1); - } - return null; + private static Status getStatus(Optional currentVersion, long lastVersion) { + if (!currentVersion.isPresent()) { + return Status.FRESH_INSTALL; + } + Long aLong = currentVersion.get(); + if (aLong == lastVersion) { + return Status.UP_TO_DATE; + } + if (aLong > lastVersion) { + return Status.REQUIRES_DOWNGRADE; } + return Status.REQUIRES_UPGRADE; } public enum Status { diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/DbVersionModuleTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationConfigurationModuleTest.java similarity index 80% rename from server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/DbVersionModuleTest.java rename to server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationConfigurationModuleTest.java index eeb1c79f347..a40329cecaf 100644 --- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/DbVersionModuleTest.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationConfigurationModuleTest.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.platform.db.migration.version; +package org.sonar.server.platform.db.migration; import org.junit.Test; import org.sonar.core.platform.ComponentContainer; @@ -25,8 +25,8 @@ import org.sonar.core.platform.ComponentContainer; import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER; -public class DbVersionModuleTest { - private DbVersionModule underTest = new DbVersionModule(); +public class MigrationConfigurationModuleTest { + private MigrationConfigurationModule underTest = new MigrationConfigurationModule(); @Test public void verify_component_count() { @@ -35,7 +35,11 @@ public class DbVersionModuleTest { underTest.configure(container); assertThat(container.getPicoContainer().getComponentAdapters()) - .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 6); + .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + // DbVersion classes + + 6 + // Others + + 3); } } diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationEngineModuleTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationEngineModuleTest.java index b2a3c5fc059..35eef3d53e6 100644 --- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationEngineModuleTest.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationEngineModuleTest.java @@ -35,6 +35,6 @@ public class MigrationEngineModuleTest { underTest.configure(container); assertThat(container.getPicoContainer().getComponentAdapters()) - .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 5); + .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 2); } } diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/DatabaseVersionTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/DatabaseVersionTest.java index ff5d406f258..58c8174bcc4 100644 --- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/DatabaseVersionTest.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/DatabaseVersionTest.java @@ -19,50 +19,62 @@ */ package org.sonar.server.platform.db.migration.version; -import org.junit.Rule; +import java.util.Optional; +import javax.annotation.Nullable; import org.junit.Test; -import org.sonar.api.utils.System2; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.DbTester; +import org.sonar.server.platform.db.migration.history.MigrationHistory; +import org.sonar.server.platform.db.migration.step.MigrationSteps; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.sonar.server.platform.db.migration.version.DatabaseVersion.Status.FRESH_INSTALL; +import static org.sonar.server.platform.db.migration.version.DatabaseVersion.Status.REQUIRES_DOWNGRADE; +import static org.sonar.server.platform.db.migration.version.DatabaseVersion.Status.REQUIRES_UPGRADE; +import static org.sonar.server.platform.db.migration.version.DatabaseVersion.Status.UP_TO_DATE; public class DatabaseVersionTest { - @Rule - public DbTester dbTester = DbTester.create(System2.INSTANCE); - - private DbClient dbClient = dbTester.getDbClient(); - private DbSession dbSession = dbTester.getSession(); - private DatabaseVersion underTest = new DatabaseVersion(dbClient); + private MigrationHistory migrationHistory = mock(MigrationHistory.class); + private MigrationSteps migrationSteps = mock(MigrationSteps.class); + private DatabaseVersion underTest = new DatabaseVersion(migrationSteps, migrationHistory); @Test - public void getVersion() { - dbTester.getDbClient().schemaMigrationDao().insert(dbSession, "1"); - dbTester.getDbClient().schemaMigrationDao().insert(dbSession, "2"); - dbTester.getDbClient().schemaMigrationDao().insert(dbSession, "4"); - dbTester.getDbClient().schemaMigrationDao().insert(dbSession, "123"); - dbTester.getDbClient().schemaMigrationDao().insert(dbSession, "50"); - dbSession.commit(); + public void getStatus_returns_FRESH_INSTALL_when_table_is_empty() { + mockMaxMigrationNumberInDb(null); + mockMaxMigrationNumberInConfig(150L); + assertThat(underTest.getStatus()).isEqualTo(FRESH_INSTALL); + } - Integer version = underTest.getVersion(); + @Test + public void getStatus_returns_REQUIRES_UPGRADE_when_max_migration_number_in_table_is_less_than_max_migration_number_in_configuration() { + mockMaxMigrationNumberInDb(123L); + mockMaxMigrationNumberInConfig(150L); - assertThat(version).isEqualTo(123); + assertThat(underTest.getStatus()).isEqualTo(REQUIRES_UPGRADE); } @Test - public void getVersion_no_rows() { - Integer version = underTest.getVersion(); + public void getStatus_returns_UP_TO_DATE_when_max_migration_number_in_table_is_equal_to_max_migration_number_in_configuration() { + mockMaxMigrationNumberInDb(150L); + mockMaxMigrationNumberInConfig(150L); - assertThat(version).isNull(); + assertThat(underTest.getStatus()).isEqualTo(UP_TO_DATE); } @Test - public void getStatus() { - assertThat(DatabaseVersion.getStatus(null, 150)).isEqualTo(DatabaseVersion.Status.FRESH_INSTALL); - assertThat(DatabaseVersion.getStatus(123, 150)).isEqualTo(DatabaseVersion.Status.REQUIRES_UPGRADE); - assertThat(DatabaseVersion.getStatus(150, 150)).isEqualTo(DatabaseVersion.Status.UP_TO_DATE); - assertThat(DatabaseVersion.getStatus(200, 150)).isEqualTo(DatabaseVersion.Status.REQUIRES_DOWNGRADE); + public void getStatus_returns_REQUIRES_DOWNGRADE_when_max_migration_number_in_table_is_greater_than_max_migration_number_in_configuration() { + mockMaxMigrationNumberInDb(200L); + mockMaxMigrationNumberInConfig(150L); + + assertThat(underTest.getStatus()).isEqualTo(REQUIRES_DOWNGRADE); + } + + private void mockMaxMigrationNumberInDb(@Nullable Long value1) { + when(migrationHistory.getLastMigrationNumber()).thenReturn(Optional.ofNullable(value1)); + } + + private void mockMaxMigrationNumberInConfig(long value) { + when(migrationSteps.getMaxMigrationNumber()).thenReturn(value); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/DatabaseServerCompatibility.java b/server/sonar-server/src/main/java/org/sonar/server/platform/DatabaseServerCompatibility.java index ad44c4e2079..99fe6279fd0 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/DatabaseServerCompatibility.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/DatabaseServerCompatibility.java @@ -19,6 +19,7 @@ */ package org.sonar.server.platform; +import java.util.Optional; import org.picocontainer.Startable; import org.sonar.api.utils.MessageException; import org.sonar.api.utils.log.Loggers; @@ -42,8 +43,8 @@ public class DatabaseServerCompatibility implements Startable { throw MessageException.of("Database was upgraded to a more recent of SonarQube. Backup must probably be restored or db settings are incorrect."); } if (status == DatabaseVersion.Status.REQUIRES_UPGRADE) { - Integer currentVersion = this.version.getVersion(); - if (currentVersion != null && currentVersion < DatabaseVersion.MIN_UPGRADE_VERSION) { + Optional currentVersion = this.version.getVersion(); + if (currentVersion.isPresent() && currentVersion.get() < DatabaseVersion.MIN_UPGRADE_VERSION) { throw MessageException.of("Current version is too old. Please upgrade to Long Term Support version firstly."); } String msg = "Database must be upgraded. Please backup database and browse /setup"; diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerUpgradeStatus.java b/server/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerUpgradeStatus.java index 56b3df3f962..0a99d097d68 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerUpgradeStatus.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerUpgradeStatus.java @@ -19,10 +19,12 @@ */ package org.sonar.server.platform; +import java.util.Optional; import org.apache.commons.lang.builder.ReflectionToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; import org.picocontainer.Startable; import org.sonar.api.platform.ServerUpgradeStatus; +import org.sonar.server.platform.db.migration.step.MigrationSteps; import org.sonar.server.platform.db.migration.version.DatabaseVersion; /** @@ -31,18 +33,20 @@ import org.sonar.server.platform.db.migration.version.DatabaseVersion; public final class DefaultServerUpgradeStatus implements ServerUpgradeStatus, Startable { private final DatabaseVersion dbVersion; + private final MigrationSteps migrationSteps; // available when connected to db - private int initialDbVersion; + private long initialDbVersion; - public DefaultServerUpgradeStatus(DatabaseVersion dbVersion) { + public DefaultServerUpgradeStatus(DatabaseVersion dbVersion, MigrationSteps migrationSteps) { this.dbVersion = dbVersion; + this.migrationSteps = migrationSteps; } @Override public void start() { - Integer v = dbVersion.getVersion(); - this.initialDbVersion = v != null ? v : -1; + Optional v = dbVersion.getVersion(); + this.initialDbVersion = v.orElse(-1L); } @Override @@ -52,7 +56,7 @@ public final class DefaultServerUpgradeStatus implements ServerUpgradeStatus, St @Override public boolean isUpgraded() { - return !isFreshInstall() && (initialDbVersion < DatabaseVersion.LAST_VERSION); + return !isFreshInstall() && (initialDbVersion < migrationSteps.getMaxMigrationNumber()); } @Override @@ -62,7 +66,7 @@ public final class DefaultServerUpgradeStatus implements ServerUpgradeStatus, St @Override public int getInitialDbVersion() { - return initialDbVersion; + return (int) initialDbVersion; } @Override diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel2.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel2.java index bd1cd454b1b..827c7c98f60 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel2.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel2.java @@ -24,15 +24,17 @@ import org.sonar.core.i18n.DefaultI18n; import org.sonar.core.i18n.RuleI18nManager; import org.sonar.core.platform.PluginClassloaderFactory; import org.sonar.core.platform.PluginLoader; -import org.sonar.server.platform.db.migration.version.DatabaseVersion; import org.sonar.server.platform.DatabaseServerCompatibility; import org.sonar.server.platform.DefaultServerUpgradeStatus; import org.sonar.server.platform.StartupMetadataProvider; import org.sonar.server.platform.db.CheckDatabaseCharsetAtStartup; import org.sonar.server.platform.db.migration.DatabaseMigrationExecutorServiceImpl; import org.sonar.server.platform.db.migration.DatabaseMigrationStateImpl; +import org.sonar.server.platform.db.migration.MigrationConfigurationModule; import org.sonar.server.platform.db.migration.charset.DatabaseCharsetChecker; +import org.sonar.server.platform.db.migration.history.MigrationHistoryTable; import org.sonar.server.platform.db.migration.history.MigrationHistoryTableImpl; +import org.sonar.server.platform.db.migration.version.DatabaseVersion; import org.sonar.server.platform.web.RailsAppsDeployer; import org.sonar.server.plugins.InstalledPluginReferentialFactory; import org.sonar.server.plugins.ServerPluginJarExploder; @@ -49,6 +51,7 @@ public class PlatformLevel2 extends PlatformLevel { @Override protected void configureLevel() { add( + MigrationConfigurationModule.class, DatabaseVersion.class, DatabaseServerCompatibility.class, @@ -75,12 +78,20 @@ public class PlatformLevel2 extends PlatformLevel { // Migration state must be kept at level2 to survive moving in and then out of safe mode // ExecutorService must be kept at level2 because stopping it when stopping safe mode level causes error making SQ fail - add(DatabaseMigrationStateImpl.class, + add( + MigrationHistoryTableImpl.class, + DatabaseMigrationStateImpl.class, DatabaseMigrationExecutorServiceImpl.class); addIfStartupLeader( - MigrationHistoryTableImpl.class, DatabaseCharsetChecker.class, CheckDatabaseCharsetAtStartup.class); } + + @Override + public PlatformLevel start() { + // ensuring the HistoryTable exists must be the first thing done when this level is started + getOptional(MigrationHistoryTable.class).ifPresent(MigrationHistoryTable::start); + return super.start(); + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelSafeMode.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelSafeMode.java index e83661bdcaa..bd4b34496f5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelSafeMode.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelSafeMode.java @@ -21,10 +21,9 @@ package org.sonar.server.platform.platformlevel; import org.sonar.server.organization.NoopDefaultOrganizationCache; import org.sonar.server.platform.ServerImpl; -import org.sonar.server.platform.db.migration.DatabaseMigrationImpl; import org.sonar.server.platform.db.migration.AutoDbMigration; +import org.sonar.server.platform.db.migration.DatabaseMigrationImpl; import org.sonar.server.platform.db.migration.MigrationEngineModule; -import org.sonar.server.platform.db.migration.version.DbVersionModule; import org.sonar.server.platform.web.WebPagesFilter; import org.sonar.server.platform.ws.DbMigrationStatusAction; import org.sonar.server.platform.ws.IndexAction; @@ -66,7 +65,6 @@ public class PlatformLevelSafeMode extends PlatformLevel { NoopDefaultOrganizationCache.class); add(DatabaseMigrationImpl.class); - add(DbVersionModule.class); addIfStartupLeader( MigrationEngineModule.class, AutoDbMigration.class); diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/DbMigrationStatusAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/DbMigrationStatusAction.java index 3e383c3ddc7..0d9959ce9bf 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/DbMigrationStatusAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/DbMigrationStatusAction.java @@ -20,13 +20,14 @@ package org.sonar.server.platform.ws; import com.google.common.io.Resources; +import java.util.Optional; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.text.JsonWriter; import org.sonar.db.Database; -import org.sonar.server.platform.db.migration.version.DatabaseVersion; import org.sonar.server.platform.db.migration.DatabaseMigrationState; +import org.sonar.server.platform.db.migration.version.DatabaseVersion; import static com.google.common.base.Preconditions.checkState; import static org.sonar.server.platform.ws.DbMigrationJsonWriter.NO_CONNECTION_TO_DB; @@ -64,12 +65,13 @@ public class DbMigrationStatusAction implements SystemWsAction { @Override public void handle(Request request, Response response) throws Exception { - Integer currentVersion = databaseVersion.getVersion(); - checkState(currentVersion != null, NO_CONNECTION_TO_DB); + Optional currentVersion = databaseVersion.getVersion(); + checkState(currentVersion.isPresent(), NO_CONNECTION_TO_DB); JsonWriter json = response.newJsonWriter(); try { - if (currentVersion >= DatabaseVersion.LAST_VERSION) { + DatabaseVersion.Status status = databaseVersion.getStatus(); + if (status == DatabaseVersion.Status.UP_TO_DATE || status == DatabaseVersion.Status.REQUIRES_DOWNGRADE) { write(json, databaseMigrationState); } else if (!database.getDialect().supportsMigration()) { writeNotSupportedResponse(json); diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/MigrateDbAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/MigrateDbAction.java index 029dd1dfd4d..720c7772714 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/MigrateDbAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/MigrateDbAction.java @@ -20,6 +20,7 @@ package org.sonar.server.platform.ws; import com.google.common.io.Resources; +import java.util.Optional; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; @@ -72,12 +73,13 @@ public class MigrateDbAction implements SystemWsAction { @Override public void handle(Request request, Response response) throws Exception { - Integer currentVersion = databaseVersion.getVersion(); - checkState(currentVersion != null, NO_CONNECTION_TO_DB); + Optional currentVersion = databaseVersion.getVersion(); + checkState(currentVersion.isPresent(), NO_CONNECTION_TO_DB); JsonWriter json = response.newJsonWriter(); try { - if (currentVersion >= DatabaseVersion.LAST_VERSION) { + DatabaseVersion.Status status = databaseVersion.getStatus(); + if (status == DatabaseVersion.Status.UP_TO_DATE || status == DatabaseVersion.Status.REQUIRES_DOWNGRADE) { write(json, migrationState); } else if (!database.getDialect().supportsMigration()) { writeNotSupportedResponse(json); diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java index de8a5bff789..15a6c001a08 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java @@ -24,6 +24,7 @@ import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; +import java.util.Optional; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.sonar.api.Plugin; @@ -308,21 +309,21 @@ public final class JRubyFacade { public boolean isSonarAccessAllowed() { ComponentContainer container = Platform.getInstance().getContainer(); DatabaseMigrationState databaseMigrationState = container.getComponentByType(DatabaseMigrationState.class); - Status status = databaseMigrationState.getStatus(); - if (status == Status.RUNNING - || status == Status.FAILED) { + Status migrationStatus = databaseMigrationState.getStatus(); + if (migrationStatus == Status.RUNNING || migrationStatus == Status.FAILED) { return false; } - if (status == Status.SUCCEEDED) { + if (migrationStatus == Status.SUCCEEDED) { return true; } DatabaseVersion databaseVersion = container.getComponentByType(DatabaseVersion.class); - Integer currentVersion = databaseVersion.getVersion(); - if (currentVersion == null) { + Optional currentVersion = databaseVersion.getVersion(); + if (!currentVersion.isPresent()) { throw new IllegalStateException("Version can not be retrieved from Database. Database is either blank or corrupted"); } - if (currentVersion >= DatabaseVersion.LAST_VERSION) { + DatabaseVersion.Status status = databaseVersion.getStatus(); + if (status == DatabaseVersion.Status.UP_TO_DATE || status == DatabaseVersion.Status.REQUIRES_DOWNGRADE) { return true; } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/DatabaseServerCompatibilityTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/DatabaseServerCompatibilityTest.java index 687e25860a8..09cbe5e2b8d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/DatabaseServerCompatibilityTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/DatabaseServerCompatibilityTest.java @@ -19,6 +19,7 @@ */ package org.sonar.server.platform; +import java.util.Optional; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -55,7 +56,7 @@ public class DatabaseServerCompatibilityTest { DatabaseVersion version = mock(DatabaseVersion.class); when(version.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_UPGRADE); - when(version.getVersion()).thenReturn(12); + when(version.getVersion()).thenReturn(Optional.of(12L)); new DatabaseServerCompatibility(version).start(); } @@ -63,7 +64,7 @@ public class DatabaseServerCompatibilityTest { public void log_warning_if_requires_upgrade() { DatabaseVersion version = mock(DatabaseVersion.class); when(version.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_UPGRADE); - when(version.getVersion()).thenReturn(DatabaseVersion.MIN_UPGRADE_VERSION); + when(version.getVersion()).thenReturn(Optional.of(DatabaseVersion.MIN_UPGRADE_VERSION)); new DatabaseServerCompatibility(version).start(); assertThat(logTester.logs()).hasSize(2); diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/DefaultServerUpgradeStatusTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/DefaultServerUpgradeStatusTest.java index 4b7f2fca8d6..256809b7dbd 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/DefaultServerUpgradeStatusTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/DefaultServerUpgradeStatusTest.java @@ -19,52 +19,58 @@ */ package org.sonar.server.platform; +import java.util.Optional; +import org.junit.Before; import org.junit.Test; +import org.sonar.server.platform.db.migration.step.MigrationSteps; import org.sonar.server.platform.db.migration.version.DatabaseVersion; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class DefaultServerUpgradeStatusTest { + private static final long LAST_VERSION = 150; + private MigrationSteps migrationSteps = mock(MigrationSteps.class); + private DatabaseVersion dbVersion = mock(DatabaseVersion.class); + private DefaultServerUpgradeStatus underTest = new DefaultServerUpgradeStatus(dbVersion, migrationSteps); + + @Before + public void setUp() throws Exception { + when(migrationSteps.getMaxMigrationNumber()).thenReturn(LAST_VERSION); + } @Test public void shouldBeFreshInstallation() { - DatabaseVersion dbVersion = mock(DatabaseVersion.class); - when(dbVersion.getVersion()).thenReturn(null); + when(migrationSteps.getMaxMigrationNumber()).thenReturn(150L); + when(dbVersion.getVersion()).thenReturn(Optional.empty()); - DefaultServerUpgradeStatus status = new DefaultServerUpgradeStatus(dbVersion); - status.start(); + underTest.start(); - assertThat(status.isFreshInstall(), is(true)); - assertThat(status.isUpgraded(), is(false)); - assertThat(status.getInitialDbVersion(), is(-1)); + assertThat(underTest.isFreshInstall()).isTrue(); + assertThat(underTest.isUpgraded()).isFalse(); + assertThat(underTest.getInitialDbVersion()).isEqualTo(-1); } @Test public void shouldBeUpgraded() { - DatabaseVersion dbVersion = mock(DatabaseVersion.class); - when(dbVersion.getVersion()).thenReturn(50); + when(dbVersion.getVersion()).thenReturn(Optional.of(50L)); - DefaultServerUpgradeStatus status = new DefaultServerUpgradeStatus(dbVersion); - status.start(); + underTest.start(); - assertThat(status.isFreshInstall(), is(false)); - assertThat(status.isUpgraded(), is(true)); - assertThat(status.getInitialDbVersion(), is(50)); + assertThat(underTest.isFreshInstall()).isFalse(); + assertThat(underTest.isUpgraded()).isTrue(); + assertThat(underTest.getInitialDbVersion()).isEqualTo(50); } @Test public void shouldNotBeUpgraded() { - DatabaseVersion dbVersion = mock(DatabaseVersion.class); - when(dbVersion.getVersion()).thenReturn(DatabaseVersion.LAST_VERSION); + when(dbVersion.getVersion()).thenReturn(Optional.of(LAST_VERSION)); - DefaultServerUpgradeStatus status = new DefaultServerUpgradeStatus(dbVersion); - status.start(); + underTest.start(); - assertThat(status.isFreshInstall(), is(false)); - assertThat(status.isUpgraded(), is(false)); - assertThat(status.getInitialDbVersion(), is(DatabaseVersion.LAST_VERSION)); + assertThat(underTest.isFreshInstall()).isFalse(); + assertThat(underTest.isUpgraded()).isFalse(); + assertThat(underTest.getInitialDbVersion()).isEqualTo((int) LAST_VERSION); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/DatabaseMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/DatabaseMonitorTest.java index 228b19650e4..3210faf6799 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/DatabaseMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/DatabaseMonitorTest.java @@ -20,6 +20,7 @@ package org.sonar.server.platform.monitoring; import java.util.Map; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.sonar.api.utils.System2; @@ -27,13 +28,21 @@ import org.sonar.db.DbTester; import org.sonar.server.platform.db.migration.version.DatabaseVersion; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class DatabaseMonitorTest { @Rule public DbTester dbTester = DbTester.create(System2.INSTANCE); - private DatabaseMonitor underTest = new DatabaseMonitor(new DatabaseVersion(dbTester.getDbClient()), dbTester.getDbClient()); + private DatabaseVersion databaseVersion = mock(DatabaseVersion.class); + private DatabaseMonitor underTest = new DatabaseMonitor(databaseVersion, dbTester.getDbClient()); + + @Before + public void setUp() throws Exception { + when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.UP_TO_DATE); + } @Test public void name_is_not_empty() { diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/platformlevel/PlatformLevel2Test.java b/server/sonar-server/src/test/java/org/sonar/server/platform/platformlevel/PlatformLevel2Test.java index 568745297f5..1cff26eb3e4 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/platformlevel/PlatformLevel2Test.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/platformlevel/PlatformLevel2Test.java @@ -52,10 +52,10 @@ public class PlatformLevel2Test { @Test public void add_all_components_by_default() { PlatformLevel1 level1 = new PlatformLevel1(mock(Platform.class), props); - level1.configureLevel(); + level1.configure(); PlatformLevel2 underTest = new PlatformLevel2(level1); - underTest.configureLevel(); + underTest.configure(); // some level1 components assertThat(underTest.getOptional(Cluster.class)).isPresent(); @@ -72,10 +72,10 @@ public class PlatformLevel2Test { public void do_not_add_all_components_when_startup_follower() { props.setProperty("sonar.cluster.enabled", "true"); PlatformLevel1 level1 = new PlatformLevel1(mock(Platform.class), props); - level1.configureLevel(); + level1.configure(); PlatformLevel2 underTest = new PlatformLevel2(level1); - underTest.configureLevel(); + underTest.configure(); assertThat(underTest.get(Cluster.class).isStartupLeader()).isFalse(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/DbMigrationStatusActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/DbMigrationStatusActionTest.java index b5c833e7d1f..e7469eca294 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/DbMigrationStatusActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/DbMigrationStatusActionTest.java @@ -20,13 +20,18 @@ package org.sonar.server.platform.ws; import com.google.common.collect.ImmutableList; +import com.tngtech.java.junit.dataprovider.DataProvider; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; import java.util.Arrays; import java.util.Date; +import java.util.Optional; import javax.annotation.Nullable; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; import org.sonar.api.server.ws.Request; import org.sonar.api.utils.DateUtils; import org.sonar.db.Database; @@ -40,6 +45,7 @@ import static com.google.common.base.Predicates.in; import static com.google.common.base.Predicates.not; import static com.google.common.collect.Iterables.filter; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.when; import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Status.FAILED; import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Status.NONE; @@ -58,6 +64,7 @@ import static org.sonar.server.platform.ws.DbMigrationJsonWriter.STATUS_NOT_SUPP import static org.sonar.server.platform.ws.DbMigrationJsonWriter.STATUS_NO_MIGRATION; import static org.sonar.test.JsonAssert.assertJson; +@RunWith(DataProviderRunner.class) public class DbMigrationStatusActionTest { @Rule public ExpectedException expectedException = ExpectedException.none(); @@ -65,9 +72,6 @@ public class DbMigrationStatusActionTest { private static final Date SOME_DATE = new Date(); private static final String SOME_THROWABLE_MSG = "blablabla pop !"; private static final String DEFAULT_ERROR_MSG = "No failure error"; - private static final int CURRENT_VERSION = DatabaseVersion.LAST_VERSION; - private static final int OLD_VERSION = CURRENT_VERSION - 1; - private static final int NEWER_VERSION = CURRENT_VERSION + 1; private DatabaseVersion databaseVersion = mock(DatabaseVersion.class); private Database database = mock(Database.class); @@ -81,11 +85,11 @@ public class DbMigrationStatusActionTest { @Before public void wireMocksTogether() { when(database.getDialect()).thenReturn(dialect); + when(databaseVersion.getVersion()).thenReturn(Optional.of(150L)); } @Test public void verify_example() throws Exception { - when(databaseVersion.getVersion()).thenReturn(OLD_VERSION); when(dialect.supportsMigration()).thenReturn(true); when(migrationState.getStatus()).thenReturn(RUNNING); when(migrationState.getStartedAt()).thenReturn(DateUtils.parseDateTime("2015-02-23T18:54:23+0100")); @@ -95,8 +99,9 @@ public class DbMigrationStatusActionTest { } @Test - public void throws_ISE_when_databaseVersion_can_not_be_determined() throws Exception { - when(databaseVersion.getVersion()).thenReturn(null); + public void throws_ISE_when_database_has_no_version() throws Exception { + reset(database); + when(databaseVersion.getVersion()).thenReturn(Optional.empty()); expectedException.expect(IllegalStateException.class); expectedException.expectMessage("Cannot connect to Database."); @@ -105,8 +110,8 @@ public class DbMigrationStatusActionTest { } @Test - public void msg_is_operational_and_state_from_databasemigration_when_databaseversion_is_equal_to_currentversion() throws Exception { - when(databaseVersion.getVersion()).thenReturn(CURRENT_VERSION); + public void msg_is_operational_and_state_from_databasemigration_when_databaseversion_status_is_UP_TO_DATE() throws Exception { + when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.UP_TO_DATE); when(migrationState.getStatus()).thenReturn(NONE); underTest.handle(request, response); @@ -116,18 +121,19 @@ public class DbMigrationStatusActionTest { // this test will raise a IllegalArgumentException when an unsupported value is added to the Status enum @Test - public void defensive_test_all_values_of_Status_must_be_supported() throws Exception { - for (Status status : filter(Arrays.asList(DatabaseMigrationState.Status.values()), not(in(ImmutableList.of(NONE, RUNNING, FAILED, SUCCEEDED))))) { - when(databaseVersion.getVersion()).thenReturn(CURRENT_VERSION); - when(migrationState.getStatus()).thenReturn(status); + @UseDataProvider("statusRequiringDbMigration") + public void defensive_test_all_values_of_Status_must_be_supported(DatabaseVersion.Status status) throws Exception { + when(databaseVersion.getStatus()).thenReturn(status); + for (Status migrationStatus : filter(Arrays.asList(DatabaseMigrationState.Status.values()), not(in(ImmutableList.of(NONE, RUNNING, FAILED, SUCCEEDED))))) { + when(migrationState.getStatus()).thenReturn(migrationStatus); underTest.handle(request, response); } } @Test - public void state_from_databasemigration_when_databaseversion_greater_than_currentversion() throws Exception { - when(databaseVersion.getVersion()).thenReturn(NEWER_VERSION); + public void state_from_databasemigration_when_databaseversion_status_is_REQUIRES_DOWNGRADE() throws Exception { + when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_DOWNGRADE); when(migrationState.getStatus()).thenReturn(NONE); underTest.handle(request, response); @@ -136,8 +142,9 @@ public class DbMigrationStatusActionTest { } @Test - public void state_is_NONE_with_specific_msg_when_version_is_less_than_current_version_and_dialect_does_not_support_migration() throws Exception { - when(databaseVersion.getVersion()).thenReturn(OLD_VERSION); + @UseDataProvider("statusRequiringDbMigration") + public void state_is_NONE_with_specific_msg_when_db_requires_upgrade_but_dialect_does_not_support_migration(DatabaseVersion.Status status) throws Exception { + when(databaseVersion.getStatus()).thenReturn(status); when(dialect.supportsMigration()).thenReturn(false); underTest.handle(request, response); @@ -146,8 +153,9 @@ public class DbMigrationStatusActionTest { } @Test - public void state_from_databasemigration_when_dbmigration_status_is_RUNNING() throws Exception { - when(databaseVersion.getVersion()).thenReturn(OLD_VERSION); + @UseDataProvider("statusRequiringDbMigration") + public void state_from_database_migration_when_dbmigration_status_is_RUNNING(DatabaseVersion.Status status) throws Exception { + when(databaseVersion.getStatus()).thenReturn(status); when(dialect.supportsMigration()).thenReturn(true); when(migrationState.getStatus()).thenReturn(RUNNING); when(migrationState.getStartedAt()).thenReturn(SOME_DATE); @@ -158,8 +166,9 @@ public class DbMigrationStatusActionTest { } @Test - public void state_from_databasemigration_and_msg_includes_error_when_dbmigration_status_is_FAILED() throws Exception { - when(databaseVersion.getVersion()).thenReturn(OLD_VERSION); + @UseDataProvider("statusRequiringDbMigration") + public void state_from_database_migration_and_msg_includes_error_when_dbmigration_status_is_FAILED(DatabaseVersion.Status status) throws Exception { + when(databaseVersion.getStatus()).thenReturn(status); when(dialect.supportsMigration()).thenReturn(true); when(migrationState.getStatus()).thenReturn(FAILED); when(migrationState.getStartedAt()).thenReturn(SOME_DATE); @@ -171,8 +180,9 @@ public class DbMigrationStatusActionTest { } @Test - public void state_from_databasemigration_and_msg_has_default_msg_when_dbmigration_status_is_FAILED() throws Exception { - when(databaseVersion.getVersion()).thenReturn(OLD_VERSION); + @UseDataProvider("statusRequiringDbMigration") + public void state_from_database_migration_and_msg_has_default_msg_when_dbmigration_status_is_FAILED(DatabaseVersion.Status status) throws Exception { + when(databaseVersion.getStatus()).thenReturn(status); when(dialect.supportsMigration()).thenReturn(true); when(migrationState.getStatus()).thenReturn(FAILED); when(migrationState.getStartedAt()).thenReturn(SOME_DATE); @@ -184,8 +194,9 @@ public class DbMigrationStatusActionTest { } @Test - public void state_from_databasemigration_and_msg_has_default_msg_when_dbmigration_status_is_SUCCEEDED() throws Exception { - when(databaseVersion.getVersion()).thenReturn(OLD_VERSION); + @UseDataProvider("statusRequiringDbMigration") + public void state_from_database_migration_and_msg_has_default_msg_when_dbmigration_status_is_SUCCEEDED(DatabaseVersion.Status status) throws Exception { + when(databaseVersion.getStatus()).thenReturn(status); when(dialect.supportsMigration()).thenReturn(true); when(migrationState.getStatus()).thenReturn(SUCCEEDED); when(migrationState.getStartedAt()).thenReturn(SOME_DATE); @@ -196,8 +207,9 @@ public class DbMigrationStatusActionTest { } @Test - public void start_migration_and_return_state_from_databasemigration_when_dbmigration_status_is_NONE() throws Exception { - when(databaseVersion.getVersion()).thenReturn(OLD_VERSION); + @UseDataProvider("statusRequiringDbMigration") + public void start_migration_and_return_state_from_databasemigration_when_dbmigration_status_is_NONE(DatabaseVersion.Status status) throws Exception { + when(databaseVersion.getStatus()).thenReturn(status); when(dialect.supportsMigration()).thenReturn(true); when(migrationState.getStatus()).thenReturn(NONE); when(migrationState.getStartedAt()).thenReturn(SOME_DATE); @@ -207,6 +219,14 @@ public class DbMigrationStatusActionTest { assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_MIGRATION_REQUIRED, MESSAGE_MIGRATION_REQUIRED)); } + @DataProvider + public static Object[][] statusRequiringDbMigration() { + return new Object[][] { + { DatabaseVersion.Status.FRESH_INSTALL }, + { DatabaseVersion.Status.REQUIRES_UPGRADE }, + }; + } + private static String failedMsg(@Nullable String t) { return "Migration failed: " + t + ".
Please check logs."; } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/MigrateDbActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/MigrateDbActionTest.java index 64ef74ad62d..06a76dc1279 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/MigrateDbActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/MigrateDbActionTest.java @@ -20,13 +20,18 @@ package org.sonar.server.platform.ws; import com.google.common.collect.ImmutableList; +import com.tngtech.java.junit.dataprovider.DataProvider; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; import java.util.Arrays; import java.util.Date; +import java.util.Optional; import javax.annotation.Nullable; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; import org.sonar.api.server.ws.Request; import org.sonar.api.utils.DateUtils; import org.sonar.db.Database; @@ -41,6 +46,7 @@ import static com.google.common.base.Predicates.in; import static com.google.common.base.Predicates.not; import static com.google.common.collect.Iterables.filter; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Status.FAILED; @@ -49,6 +55,7 @@ import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Stat import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Status.SUCCEEDED; import static org.sonar.test.JsonAssert.assertJson; +@RunWith(DataProviderRunner.class) public class MigrateDbActionTest { @Rule public ExpectedException expectedException = ExpectedException.none(); @@ -56,9 +63,6 @@ public class MigrateDbActionTest { private static final Date SOME_DATE = new Date(); private static final String SOME_THROWABLE_MSG = "blablabla pop !"; private static final String DEFAULT_ERROR_MSG = "No failure error"; - private static final int CURRENT_VERSION = DatabaseVersion.LAST_VERSION; - private static final int OLD_VERSION = CURRENT_VERSION - 1; - private static final int NEWER_VERSION = CURRENT_VERSION + 1; private static final String STATUS_NO_MIGRATION = "NO_MIGRATION"; private static final String STATUS_NOT_SUPPORTED = "NOT_SUPPORTED"; @@ -84,11 +88,13 @@ public class MigrateDbActionTest { @Before public void wireMocksTogether() { when(database.getDialect()).thenReturn(dialect); + when(databaseVersion.getVersion()).thenReturn(Optional.of(150L)); } @Test public void ISE_is_thrown_when_version_can_not_be_retrieved_from_database() throws Exception { - when(databaseVersion.getVersion()).thenReturn(null); + reset(databaseVersion); + when(databaseVersion.getVersion()).thenReturn(Optional.empty()); expectedException.expect(IllegalStateException.class); expectedException.expectMessage("Cannot connect to Database."); @@ -98,7 +104,6 @@ public class MigrateDbActionTest { @Test public void verify_example() throws Exception { - when(databaseVersion.getVersion()).thenReturn(OLD_VERSION); when(dialect.supportsMigration()).thenReturn(true); when(migrationState.getStatus()).thenReturn(RUNNING); when(migrationState.getStartedAt()).thenReturn(DateUtils.parseDateTime("2015-02-23T18:54:23+0100")); @@ -108,8 +113,8 @@ public class MigrateDbActionTest { } @Test - public void msg_is_operational_and_state_from_database_migration_when_database_version_is_equal_to_current_version() throws Exception { - when(databaseVersion.getVersion()).thenReturn(CURRENT_VERSION); + public void msg_is_operational_and_state_from_database_migration_when_databaseversion_status_is_UP_TO_DATE() throws Exception { + when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.UP_TO_DATE); when(migrationState.getStatus()).thenReturn(NONE); underTest.handle(request, response); @@ -119,9 +124,8 @@ public class MigrateDbActionTest { // this test will raise a IllegalArgumentException when an unsupported value is added to the Status enum @Test - public void defensive_test_all_values_of_Status_must_be_supported() throws Exception { + public void defensive_test_all_values_of_migration_Status_must_be_supported() throws Exception { for (Status status : filter(Arrays.asList(DatabaseMigrationState.Status.values()), not(in(ImmutableList.of(NONE, RUNNING, FAILED, SUCCEEDED))))) { - when(databaseVersion.getVersion()).thenReturn(CURRENT_VERSION); when(migrationState.getStatus()).thenReturn(status); underTest.handle(request, response); @@ -129,8 +133,8 @@ public class MigrateDbActionTest { } @Test - public void state_from_database_migration_when_databaseversion_greater_than_currentversion() throws Exception { - when(databaseVersion.getVersion()).thenReturn(NEWER_VERSION); + public void state_from_database_migration_when_databaseversion_status_is_REQUIRES_DOWNGRADE() throws Exception { + when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_DOWNGRADE); when(migrationState.getStatus()).thenReturn(NONE); underTest.handle(request, response); @@ -139,8 +143,9 @@ public class MigrateDbActionTest { } @Test - public void state_is_NONE_with_specific_msg_when_version_is_less_than_current_version_and_dialect_does_not_support_migration() throws Exception { - when(databaseVersion.getVersion()).thenReturn(OLD_VERSION); + @UseDataProvider("statusRequiringDbMigration") + public void state_is_NONE_with_specific_msg_when_db_requires_upgrade_but_dialect_does_not_support_migration(DatabaseVersion.Status status) throws Exception { + when(databaseVersion.getStatus()).thenReturn(status); when(dialect.supportsMigration()).thenReturn(false); underTest.handle(request, response); @@ -149,8 +154,9 @@ public class MigrateDbActionTest { } @Test - public void state_from_database_migration_when_dbmigration_status_is_RUNNING() throws Exception { - when(databaseVersion.getVersion()).thenReturn(OLD_VERSION); + @UseDataProvider("statusRequiringDbMigration") + public void state_from_database_migration_when_dbmigration_status_is_RUNNING(DatabaseVersion.Status status) throws Exception { + when(databaseVersion.getStatus()).thenReturn(status); when(dialect.supportsMigration()).thenReturn(true); when(migrationState.getStatus()).thenReturn(RUNNING); when(migrationState.getStartedAt()).thenReturn(SOME_DATE); @@ -161,8 +167,9 @@ public class MigrateDbActionTest { } @Test - public void state_from_database_migration_and_msg_includes_error_when_dbmigration_status_is_FAILED() throws Exception { - when(databaseVersion.getVersion()).thenReturn(OLD_VERSION); + @UseDataProvider("statusRequiringDbMigration") + public void state_from_database_migration_and_msg_includes_error_when_dbmigration_status_is_FAILED(DatabaseVersion.Status status) throws Exception { + when(databaseVersion.getStatus()).thenReturn(status); when(dialect.supportsMigration()).thenReturn(true); when(migrationState.getStatus()).thenReturn(FAILED); when(migrationState.getStartedAt()).thenReturn(SOME_DATE); @@ -174,8 +181,9 @@ public class MigrateDbActionTest { } @Test - public void state_from_database_migration_and_msg_has_default_msg_when_dbmigration_status_is_FAILED() throws Exception { - when(databaseVersion.getVersion()).thenReturn(OLD_VERSION); + @UseDataProvider("statusRequiringDbMigration") + public void state_from_database_migration_and_msg_has_default_msg_when_dbmigration_status_is_FAILED(DatabaseVersion.Status status) throws Exception { + when(databaseVersion.getStatus()).thenReturn(status); when(dialect.supportsMigration()).thenReturn(true); when(migrationState.getStatus()).thenReturn(FAILED); when(migrationState.getStartedAt()).thenReturn(SOME_DATE); @@ -187,8 +195,9 @@ public class MigrateDbActionTest { } @Test - public void state_from_database_migration_and_msg_has_default_msg_when_dbmigration_status_is_SUCCEEDED() throws Exception { - when(databaseVersion.getVersion()).thenReturn(OLD_VERSION); + @UseDataProvider("statusRequiringDbMigration") + public void state_from_database_migration_and_msg_has_default_msg_when_dbmigration_status_is_SUCCEEDED(DatabaseVersion.Status status) throws Exception { + when(databaseVersion.getStatus()).thenReturn(status); when(dialect.supportsMigration()).thenReturn(true); when(migrationState.getStatus()).thenReturn(SUCCEEDED); when(migrationState.getStartedAt()).thenReturn(SOME_DATE); @@ -199,8 +208,9 @@ public class MigrateDbActionTest { } @Test - public void start_migration_and_return_state_from_database_migration_when_dbmigration_status_is_NONE() throws Exception { - when(databaseVersion.getVersion()).thenReturn(OLD_VERSION); + @UseDataProvider("statusRequiringDbMigration") + public void start_migration_and_return_state_from_databasemigration_when_dbmigration_status_is_NONE(DatabaseVersion.Status status) throws Exception { + when(databaseVersion.getStatus()).thenReturn(status); when(dialect.supportsMigration()).thenReturn(true); when(migrationState.getStatus()).thenReturn(NONE); when(migrationState.getStartedAt()).thenReturn(SOME_DATE); @@ -211,6 +221,14 @@ public class MigrateDbActionTest { assertJson(response.outputAsString()).isSimilarTo(expectedResponse(STATUS_MIGRATION_RUNNING, MESSAGE_STATUS_RUNNING, SOME_DATE)); } + @DataProvider + public static Object[][] statusRequiringDbMigration() { + return new Object[][] { + { DatabaseVersion.Status.FRESH_INSTALL }, + { DatabaseVersion.Status.REQUIRES_UPGRADE }, + }; + } + private static String failedMsg(@Nullable String t) { return "Migration failed: " + t + ".
Please check logs."; } -- 2.39.5