metrics: tests, conditions_to_cover, new_conditions_to_covertags/7.6
@@ -29,6 +29,8 @@ public class DbVersion76 implements DbVersion { | |||
registry | |||
.add(2500, "Create table USER_PROPERTIES", CreateUserPropertiesTable.class) | |||
.add(2501, "Add index in table USER_PROPERTIES", AddUniqueIndexInUserPropertiesTable.class) | |||
.add(2506, "Migrate quality gate conditions using warning, period and no more supported operations", MigrateNoMoreUsedQualityGateConditions.class); | |||
.add(2505, "Fix the direction values of certain metrics (prepare for migration of conditions)", FixDirectionOfMetrics.class) | |||
.add(2506, "Migrate quality gate conditions using warning, period and no more supported operations", MigrateNoMoreUsedQualityGateConditions.class) | |||
; | |||
} | |||
} |
@@ -0,0 +1,59 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 SonarSource SA | |||
* mailto:info 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.v76; | |||
import java.sql.SQLException; | |||
import org.sonar.db.Database; | |||
import org.sonar.server.platform.db.migration.SupportsBlueGreen; | |||
import org.sonar.server.platform.db.migration.step.DataChange; | |||
@SupportsBlueGreen | |||
public class FixDirectionOfMetrics extends DataChange { | |||
public FixDirectionOfMetrics(Database db) { | |||
super(db); | |||
} | |||
@Override | |||
protected void execute(Context context) throws SQLException { | |||
String sql = "UPDATE metrics SET direction = ? WHERE name = ? AND direction != ?"; | |||
context.prepareUpsert(sql) | |||
.setInt(1, 1) | |||
.setString(2, "tests") | |||
.setInt(3, 1) | |||
.execute() | |||
.commit(); | |||
context.prepareUpsert(sql) | |||
.setInt(1, -1) | |||
.setString(2, "conditions_to_cover") | |||
.setInt(3, -1) | |||
.execute() | |||
.commit(); | |||
context.prepareUpsert(sql) | |||
.setInt(1, -1) | |||
.setString(2, "new_conditions_to_cover") | |||
.setInt(3, -1) | |||
.execute() | |||
.commit(); | |||
} | |||
} |
@@ -35,7 +35,7 @@ public class DbVersion76Test { | |||
@Test | |||
public void verify_migration_count() { | |||
verifyMigrationCount(underTest, 3); | |||
verifyMigrationCount(underTest, 4); | |||
} | |||
} |
@@ -0,0 +1,101 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 SonarSource SA | |||
* mailto:info 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.v76; | |||
import com.google.common.collect.ImmutableMap; | |||
import com.tngtech.java.junit.dataprovider.DataProvider; | |||
import com.tngtech.java.junit.dataprovider.DataProviderRunner; | |||
import com.tngtech.java.junit.dataprovider.UseDataProvider; | |||
import java.sql.SQLException; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.runner.RunWith; | |||
import org.sonar.db.CoreDbTester; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@RunWith(DataProviderRunner.class) | |||
public class FixDirectionOfMetricsTest { | |||
private static final String TESTS_METRIC_NAME = "tests"; | |||
private static final String CONDITIONS_TO_COVER_METRIC_NAME = "conditions_to_cover"; | |||
private static final String NEW_CONDITIONS_TO_COVER_METRIC_NAME = "new_conditions_to_cover"; | |||
private static final String UNRELATED_METRIC_NAME = "unrelated"; | |||
@Rule | |||
public CoreDbTester db = CoreDbTester.createForSchema(FixDirectionOfMetricsTest.class, "metrics.sql"); | |||
private static long idCounter = 1; | |||
private FixDirectionOfMetrics underTest = new FixDirectionOfMetrics(db.database()); | |||
@Test | |||
@UseDataProvider("interestingCombinationsOfInitialMetricsAndValues") | |||
public void fixes_direction_of_relevant_metrics(Map<String, Integer> initialMetricsAndValues) throws SQLException { | |||
insertMetric(TESTS_METRIC_NAME, initialMetricsAndValues.get(TESTS_METRIC_NAME)); | |||
insertMetric(CONDITIONS_TO_COVER_METRIC_NAME, initialMetricsAndValues.get(CONDITIONS_TO_COVER_METRIC_NAME)); | |||
insertMetric(NEW_CONDITIONS_TO_COVER_METRIC_NAME, initialMetricsAndValues.get(NEW_CONDITIONS_TO_COVER_METRIC_NAME)); | |||
insertMetric(UNRELATED_METRIC_NAME, initialMetricsAndValues.get(UNRELATED_METRIC_NAME)); | |||
underTest.execute(); | |||
assertThat(selectMetricDirection(TESTS_METRIC_NAME)).isEqualTo(1L); | |||
assertThat(selectMetricDirection(CONDITIONS_TO_COVER_METRIC_NAME)).isEqualTo(-1L); | |||
assertThat(selectMetricDirection(NEW_CONDITIONS_TO_COVER_METRIC_NAME)).isEqualTo(-1L); | |||
assertThat(selectMetricDirection(UNRELATED_METRIC_NAME)).isEqualTo((long) initialMetricsAndValues.get(UNRELATED_METRIC_NAME)); | |||
} | |||
@DataProvider | |||
public static Object[][] interestingCombinationsOfInitialMetricsAndValues() { | |||
List<Map<String, Integer>> mappings = new ArrayList<>(); | |||
int[] directions = {-1, 0, 1}; | |||
for (int unrelatedDirection : directions) { | |||
// the target metrics with old (wrong) direction, and an unrelated metric with any direction | |||
mappings.add(ImmutableMap.of( | |||
TESTS_METRIC_NAME, -1, | |||
CONDITIONS_TO_COVER_METRIC_NAME, 0, | |||
NEW_CONDITIONS_TO_COVER_METRIC_NAME, 0, | |||
UNRELATED_METRIC_NAME, unrelatedDirection)); | |||
// the target metrics with correct direction, and an unrelated metric with any direction | |||
mappings.add(ImmutableMap.of( | |||
TESTS_METRIC_NAME, 1, | |||
CONDITIONS_TO_COVER_METRIC_NAME, -1, | |||
NEW_CONDITIONS_TO_COVER_METRIC_NAME, -1, | |||
UNRELATED_METRIC_NAME, unrelatedDirection)); | |||
} | |||
return mappings.stream().map(m -> new Object[] {m}).toArray(Object[][]::new); | |||
} | |||
private void insertMetric(String name, int direction) { | |||
long id = idCounter++; | |||
db.executeInsert("METRICS", | |||
"ID", id, | |||
"NAME", name, | |||
"DIRECTION", direction); | |||
} | |||
private long selectMetricDirection(String metricName) { | |||
return (long) db.selectFirst("SELECT direction FROM metrics WHERE name = '" + metricName + "'").get("DIRECTION"); | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
CREATE TABLE "METRICS" ( | |||
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||
"NAME" VARCHAR(64) NOT NULL, | |||
"DESCRIPTION" VARCHAR(255), | |||
"DIRECTION" INTEGER NOT NULL DEFAULT 0, | |||
"DOMAIN" VARCHAR(64), | |||
"SHORT_NAME" VARCHAR(64), | |||
"QUALITATIVE" BOOLEAN NOT NULL DEFAULT FALSE, | |||
"VAL_TYPE" VARCHAR(8), | |||
"USER_MANAGED" BOOLEAN DEFAULT FALSE, | |||
"ENABLED" BOOLEAN DEFAULT TRUE, | |||
"WORST_VALUE" DOUBLE, | |||
"BEST_VALUE" DOUBLE, | |||
"OPTIMIZED_BEST_VALUE" BOOLEAN, | |||
"HIDDEN" BOOLEAN, | |||
"DELETE_HISTORICAL_DATA" BOOLEAN, | |||
"DECIMAL_SCALE" INTEGER | |||
); | |||
CREATE UNIQUE INDEX "METRICS_UNIQUE_NAME" ON "METRICS" ("NAME"); |
@@ -524,7 +524,7 @@ public final class CoreMetrics { | |||
*/ | |||
public static final Metric<Integer> TESTS = new Metric.Builder(TESTS_KEY, "Unit Tests", Metric.ValueType.INT) | |||
.setDescription("Number of unit tests") | |||
.setDirection(Metric.DIRECTION_WORST) | |||
.setDirection(Metric.DIRECTION_BETTER) | |||
.setQualitative(false) | |||
.setDomain(DOMAIN_COVERAGE) | |||
.create(); | |||
@@ -704,12 +704,14 @@ public final class CoreMetrics { | |||
public static final Metric<Integer> CONDITIONS_TO_COVER = new Metric.Builder(CONDITIONS_TO_COVER_KEY, "Conditions to Cover", Metric.ValueType.INT) | |||
.setDescription("Conditions to cover") | |||
.setDomain(DOMAIN_COVERAGE) | |||
.setDirection(Metric.DIRECTION_WORST) | |||
.create(); | |||
public static final String NEW_CONDITIONS_TO_COVER_KEY = "new_conditions_to_cover"; | |||
public static final Metric<Integer> NEW_CONDITIONS_TO_COVER = new Metric.Builder(NEW_CONDITIONS_TO_COVER_KEY, "Conditions to Cover on New Code", Metric.ValueType.INT) | |||
.setDescription("Conditions to cover on new code") | |||
.setDomain(DOMAIN_COVERAGE) | |||
.setDirection(Metric.DIRECTION_WORST) | |||
.setDeleteHistoricalData(true) | |||
.create(); | |||