]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8445 drop field DatabaseVersion.LAST_VERSION 1468/head
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 15 Dec 2016 14:19:48 +0000 (15:19 +0100)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Fri, 16 Dec 2016 13:35:29 +0000 (14:35 +0100)
replace usages of this field by either MigrationSteps.getMaxMigrationNumber() or DatabaseVersion.getStatus()
also, change return type of DatabaseVersion.getVersion from int to Optional<Long>
MigrationStep configuration is now avaiable at level2, in both web and CE container (because it is used by DatabaseVersion class)

24 files changed:
server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java [new file with mode: 0644]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationEngineModule.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImpl.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/DatabaseVersion.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/DbVersionModule.java [deleted file]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationConfigurationModuleTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationEngineModuleTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/DatabaseVersionTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/DbVersionModuleTest.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/platform/DatabaseServerCompatibility.java
server/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerUpgradeStatus.java
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel2.java
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelSafeMode.java
server/sonar-server/src/main/java/org/sonar/server/platform/ws/DbMigrationStatusAction.java
server/sonar-server/src/main/java/org/sonar/server/platform/ws/MigrateDbAction.java
server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
server/sonar-server/src/test/java/org/sonar/server/platform/DatabaseServerCompatibilityTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/DefaultServerUpgradeStatusTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/DatabaseMonitorTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/platformlevel/PlatformLevel2Test.java
server/sonar-server/src/test/java/org/sonar/server/platform/ws/DbMigrationStatusActionTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/ws/MigrateDbActionTest.java

index 0b13b6fc8326456d2625abe4e1eda10ce39da971..2b82ec5d1946ea64ea7be86e6dc1684ea4af5f9c 100644 (file)
@@ -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,
 
index 6b915dd564840f9a8560a8ae9fb487bc76e067d9..87e2eb8a96930baa8d9ca7f742072ce379310c0d 100644 (file)
@@ -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/MigrationConfigurationModule.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java
new file mode 100644 (file)
index 0000000..dc41da4
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * 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;
+
+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;
+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 MigrationConfigurationModule extends Module {
+  @Override
+  protected void configureModule() {
+    add(
+      // DbVersion implementations
+      DbVersion56.class,
+      DbVersion561.class,
+      DbVersion60.class,
+      DbVersion61.class,
+      DbVersion62.class,
+      DbVersion63.class,
+
+      // migration steps
+      MigrationStepRegistryImpl.class,
+      new MigrationStepsProvider(),
+
+      // history
+      MigrationHistoryImpl.class);
+  }
+}
index 69ca3930f5f047a1fadb2984f93c357e207b7f52..620161f93f9c560af1986e5314b4dc86cf193fb8 100644 (file)
@@ -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);
   }
index b1fc36497ad0dfd58149dff0c2b6d53b4eec6b54..155cf150eb50eb970cf4069af1463340ece2479c 100644 (file)
@@ -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;
 
index cfe8a89f23ec2f39d16cc4f33eb9c4aa2ff7e039..a3ffa84f870657f946f25f501bbed1e9a776d066 100644 (file)
  */
 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<Long> getVersion() {
+    return migrationHistory.getLastMigrationNumber();
+  }
 
-      List<Integer> versions = dbClient.schemaMigrationDao().selectVersions(dbSession);
-      if (!versions.isEmpty()) {
-        Collections.sort(versions);
-        return versions.get(versions.size() - 1);
-      }
-      return null;
+  private static Status getStatus(Optional<Long> 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/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/version/DbVersionModule.java
deleted file mode 100644 (file)
index 0de1379..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * 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;
-
-import org.sonar.core.platform.Module;
-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;
-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 {
-  @Override
-  protected void configureModule() {
-    add(
-      DbVersion56.class,
-      DbVersion561.class,
-      DbVersion60.class,
-      DbVersion61.class,
-      DbVersion62.class,
-      DbVersion63.class);
-  }
-
-}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationConfigurationModuleTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationConfigurationModuleTest.java
new file mode 100644 (file)
index 0000000..a40329c
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * 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;
+
+import org.junit.Test;
+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 MigrationConfigurationModuleTest {
+  private MigrationConfigurationModule underTest = new MigrationConfigurationModule();
+
+  @Test
+  public void verify_component_count() {
+    ComponentContainer container = new ComponentContainer();
+
+    underTest.configure(container);
+
+    assertThat(container.getPicoContainer().getComponentAdapters())
+      .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER
+        // DbVersion classes
+        + 6
+        // Others
+        + 3);
+  }
+
+}
index b2a3c5fc05962a1e17d7c199b5b4f9c2470d2887..35eef3d53e602398a74bc4b83db6a52547d6082c 100644 (file)
@@ -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);
   }
 }
index ff5d406f258c8e6d3317826f1501d6b0a9f184ec..58c8174bcc4b1436365a5c246554667f35c8f763 100644 (file)
  */
 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-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/version/DbVersionModuleTest.java
deleted file mode 100644 (file)
index eeb1c79..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * 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;
-
-import org.junit.Test;
-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();
-
-  @Test
-  public void verify_component_count() {
-    ComponentContainer container = new ComponentContainer();
-
-    underTest.configure(container);
-
-    assertThat(container.getPicoContainer().getComponentAdapters())
-      .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 6);
-  }
-
-}
index ad44c4e20790fa39655a421e49a38c45809ccc91..99fe6279fd057b23cdafec01b1dacdb59627cdec 100644 (file)
@@ -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<Long> 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";
index 56b3df3f96214de1f343f0040b7ac23deb64c509..0a99d097d6805053d81b7bdd32fe566118100378 100644 (file)
  */
 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<Long> 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
index bd1cd454b1b69d008c8ddc14e99a4b05438122db..827c7c98f608354a0d1f84d84255118cb0454bfa 100644 (file)
@@ -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();
+  }
 }
index e83661bdcaa07109029d3782b08433ca729e8ff4..bd4b34496f512b47ccc61751afe5c539bcbc04fc 100644 (file)
@@ -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);
index 3e383c3ddc735e803b5edfa9aa6ee8f9844f7532..0d9959ce9bfa695b2cc271fb743a4412618ee9e2 100644 (file)
 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<Long> 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);
index 029dd1dfd4dbb4ee6ce70782b867aed11583516e..720c777271441b3f8cd5be63a2b978f7df57279a 100644 (file)
@@ -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<Long> 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);
index de8a5bff7894bd4c0e77299e1d972295b17d9f83..15a6c001a08202ee4f194d19f0e1c582bc916840 100644 (file)
@@ -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<Long> 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;
     }
 
index 687e25860a85730799d7392099594b380438fe29..09cbe5e2b8d76335ee12c5cfdb407e7c91eaded5 100644 (file)
@@ -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);
index 4b7f2fca8d693965950a1f87a738f972069acda8..256809b7dbd876d54c9e9bd319b4b9019c3f6060 100644 (file)
  */
 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);
   }
 }
index 228b19650e4203074a71cb92d26a6cd21dad07bd..3210faf67992cde657e2bd44c7f048ce73806344 100644 (file)
@@ -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() {
index 568745297f519a6a3ebcd4bd8fe06f4749f64e1d..1cff26eb3e4c4b37d1fecdd078327584795e6b55 100644 (file)
@@ -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();
 
index b5c833e7d1f1b9a71fd062c648dcfffc87da00b7..e7469eca2942449956c000b0484bddc075680510 100644 (file)
 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 + ".<br/> Please check logs.";
   }
index 64ef74ad62de5e6a5f9d01fab42a42ecbaeb058a..06a76dc127936e4eee26e1d566c10284aeca7dd3 100644 (file)
 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 + ".<br/> Please check logs.";
   }