diff options
author | Eric Giffon <eric.giffon@sonarsource.com> | 2024-09-17 16:25:13 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2024-10-09 20:02:46 +0000 |
commit | 82225b439672af6d35d463b48001452321459ff4 (patch) | |
tree | 3036731e7a7adee7901856a0f453d2d942a5dce4 | |
parent | 0ff9b7313c17474a867f744aa63afd94795a134b (diff) | |
download | sonarqube-82225b439672af6d35d463b48001452321459ff4.tar.gz sonarqube-82225b439672af6d35d463b48001452321459ff4.zip |
SONAR-22873 Read JSON measures (#11683)
Co-authored-by: Claire Villard <claire.villard@sonarsource.com>
67 files changed, 1443 insertions, 1394 deletions
diff --git a/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/PersistMeasuresStepTest.java b/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/PersistMeasuresStepTest.java index 6c7ac0e1b52..7bcbd114609 100644 --- a/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/PersistMeasuresStepTest.java +++ b/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/PersistMeasuresStepTest.java @@ -266,7 +266,7 @@ class PersistMeasuresStepTest { assertThatMeasureDoesNotExist("file-uuid", METRIC_WITH_BEST_VALUE.getKey()); - Optional<MeasureDto> persisted = dbClient.measureDao().selectMeasure(db.getSession(), "project-uuid"); + Optional<MeasureDto> persisted = dbClient.measureDao().selectByComponentUuid(db.getSession(), "project-uuid"); assertThat(persisted).isPresent(); assertThat(persisted.get().getMetricValues()).containsEntry(METRIC_WITH_BEST_VALUE.getKey(), (double) 0); @@ -311,7 +311,7 @@ class PersistMeasuresStepTest { } private void assertThatMeasureDoesNotExist(String componentUuid, String metricKey) { - assertThat(dbClient.measureDao().selectMeasure(db.getSession(), componentUuid)) + assertThat(dbClient.measureDao().selectByComponentUuid(db.getSession(), componentUuid)) .hasValueSatisfying(measureDto -> assertThat(measureDto.getMetricValues()).doesNotContainKey(metricKey)); } @@ -355,7 +355,7 @@ class PersistMeasuresStepTest { } private Optional<MeasureDto> selectMeasure(String componentUuid) { - return dbClient.measureDao().selectMeasure(db.getSession(), componentUuid); + return dbClient.measureDao().selectByComponentUuid(db.getSession(), componentUuid); } private ComponentDto insertComponent(String key, String uuid) { diff --git a/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/ProjectNclocComputationStepIT.java b/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/ProjectNclocComputationStepIT.java index a5c4f74efb7..20d42e4b786 100644 --- a/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/ProjectNclocComputationStepIT.java +++ b/server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/ProjectNclocComputationStepIT.java @@ -50,9 +50,9 @@ public class ProjectNclocComputationStepIT { MetricDto ncloc = db.measures().insertMetric(m -> m.setKey("ncloc").setValueType(INT.toString())); ProjectDto project = db.components().insertPublicProject().getProjectDto(); BranchDto branch1 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH)); - db.measures().insertLiveMeasure(branch1, ncloc, m -> m.setValue(200d)); + db.measures().insertMeasure(branch1, m -> m.addValue(ncloc.getKey(), 200d)); BranchDto branch2 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH)); - db.measures().insertLiveMeasure(branch2, ncloc, m -> m.setValue(10d)); + db.measures().insertMeasure(branch2, m -> m.addValue(ncloc.getKey(), 10d)); analysisMetadataHolder.setProject(new Project(project.getUuid(), project.getKey(), project.getName(), project.getDescription(), emptyList())); step.execute(TestComputationStepContext.TestStatistics::new); diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/Measure.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/Measure.java index 5fa29a96ac3..ac3b8c090ef 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/Measure.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/Measure.java @@ -26,12 +26,14 @@ import java.util.Objects; import java.util.Optional; import javax.annotation.CheckForNull; import javax.annotation.Nullable; +import org.sonar.ce.task.projectanalysis.metric.Metric; import org.sonar.ce.task.projectanalysis.util.cache.DoubleCache; import static com.google.common.base.MoreObjects.toStringHelper; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; +import static org.sonar.ce.task.projectanalysis.measure.Measure.Level.toLevel; public interface Measure { @@ -459,6 +461,22 @@ public interface Measure { return new MeasureImpl(ValueType.LEVEL, null, null, requireNonNull(level), qualityGateStatus); } + public Measure create(Metric metric, @Nullable Object value) { + if (value == null) { + return createNoValue(); + } + + return switch (metric.getType().getValueType()) { + case INT -> create(((Double) value).intValue()); + case LONG -> create(((Double) value).longValue()); + case DOUBLE -> create((Double) value); + case BOOLEAN -> create(Double.compare((Double) value, 1.0D) == 0); + case STRING -> create((String) value); + case LEVEL -> toLevel((String) value).map(this::create).orElse(createNoValue()); + case NO_VALUE -> createNoValue(); + }; + } + public Measure createNoValue() { if (qualityGateStatus == null) { return new NoValueMeasureImpl(); diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistMeasuresStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistMeasuresStep.java index 456d72e1286..d0d0513e85f 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistMeasuresStep.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistMeasuresStep.java @@ -141,7 +141,7 @@ public class PersistMeasuresStep implements ComputationStep { private Set<MeasureHash> getDBMeasureHashes() { try (DbSession dbSession = dbClient.openSession(false)) { - return dbClient.measureDao().selectBranchMeasureHashes(dbSession, treeRootHolder.getRoot().getUuid()); + return dbClient.measureDao().selectMeasureHashesForBranch(dbSession, treeRootHolder.getRoot().getUuid()); } } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ProjectNclocComputationStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ProjectNclocComputationStep.java index d309938cb68..031208c1c2a 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ProjectNclocComputationStep.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ProjectNclocComputationStep.java @@ -19,10 +19,14 @@ */ package org.sonar.ce.task.projectanalysis.step; +import java.util.List; import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; import org.sonar.ce.task.step.ComputationStep; import org.sonar.db.DbClient; import org.sonar.db.DbSession; +import org.sonar.db.measure.MeasureDto; + +import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; public class ProjectNclocComputationStep implements ComputationStep { @@ -38,7 +42,7 @@ public class ProjectNclocComputationStep implements ComputationStep { public void execute(Context context) { try (DbSession dbSession = dbClient.openSession(false)) { String projectUuid = analysisMetadataHolder.getProject().getUuid(); - long maxncloc = dbClient.liveMeasureDao().findNclocOfBiggestBranchForProject(dbSession, projectUuid); + long maxncloc = dbClient.measureDao().findNclocOfBiggestBranchForProject(dbSession, projectUuid); dbClient.projectDao().updateNcloc(dbSession, projectUuid, maxncloc); dbSession.commit(); } diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureTest.java index 215ca8fe80e..dab813fe5fc 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureTest.java @@ -19,22 +19,22 @@ */ package org.sonar.ce.task.projectanalysis.measure; -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.List; -import org.junit.Test; -import org.junit.runner.RunWith; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.sonar.ce.task.projectanalysis.measure.Measure.ValueType; +import org.sonar.ce.task.projectanalysis.metric.Metric; +import org.sonar.ce.task.projectanalysis.metric.MetricImpl; import org.sonar.ce.task.projectanalysis.util.WrapInSingleElementArray; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder; -@RunWith(DataProviderRunner.class) -public class MeasureTest { +class MeasureTest { private static final Measure INT_MEASURE = newMeasureBuilder().create(1); private static final Measure LONG_MEASURE = newMeasureBuilder().create(1L); @@ -45,42 +45,41 @@ public class MeasureTest { private static final Measure LEVEL_MEASURE = newMeasureBuilder().create(Measure.Level.OK); private static final Measure NO_VALUE_MEASURE = newMeasureBuilder().createNoValue(); - private static final List<Measure> MEASURES = ImmutableList.of( + private static final List<Measure> MEASURES = List.of( INT_MEASURE, LONG_MEASURE, DOUBLE_MEASURE, STRING_MEASURE, TRUE_MEASURE, FALSE_MEASURE, NO_VALUE_MEASURE, LEVEL_MEASURE); + private static final Metric INT_METRIC = new MetricImpl("42", "int", "name", Metric.MetricType.INT); + private static final Metric LONG_METRIC = new MetricImpl("42", "long", "name", Metric.MetricType.WORK_DUR); + private static final Metric DOUBLE_METRIC = new MetricImpl("42", "double", "name", Metric.MetricType.FLOAT, 5, null, false, false); + private static final Metric STRING_METRIC = new MetricImpl("42", "string", "name", Metric.MetricType.STRING); + private static final Metric BOOLEAN_METRIC = new MetricImpl("42", "boolean", "name", Metric.MetricType.BOOL); + private static final Metric LEVEL_METRIC = new MetricImpl("42", "level", "name", Metric.MetricType.LEVEL); - @DataProvider - public static Object[][] all_but_INT_MEASURE() { + private static Object[][] all_but_INT_MEASURE() { return getMeasuresExcept(ValueType.INT); } - @DataProvider - public static Object[][] all_but_LONG_MEASURE() { + private static Object[][] all_but_LONG_MEASURE() { return getMeasuresExcept(ValueType.LONG); } - @DataProvider - public static Object[][] all_but_DOUBLE_MEASURE() { + private static Object[][] all_but_DOUBLE_MEASURE() { return getMeasuresExcept(ValueType.DOUBLE); } - @DataProvider - public static Object[][] all_but_BOOLEAN_MEASURE() { + private static Object[][] all_but_BOOLEAN_MEASURE() { return getMeasuresExcept(ValueType.BOOLEAN); } - @DataProvider - public static Object[][] all_but_STRING_MEASURE() { + private static Object[][] all_but_STRING_MEASURE() { return getMeasuresExcept(ValueType.STRING); } - @DataProvider - public static Object[][] all_but_LEVEL_MEASURE() { + private static Object[][] all_but_LEVEL_MEASURE() { return getMeasuresExcept(ValueType.LEVEL); } - @DataProvider - public static Object[][] all() { + private static Object[][] all() { return MEASURES.stream().map(WrapInSingleElementArray.INSTANCE).toArray(Object[][]::new); } @@ -92,131 +91,131 @@ public class MeasureTest { } @Test - public void create_from_String_throws_NPE_if_arg_is_null() { + void create_from_String_throws_NPE_if_arg_is_null() { assertThatThrownBy(() -> newMeasureBuilder().create((String) null)) .isInstanceOf(NullPointerException.class); } @Test - public void create_from_int_has_INT_value_type() { + void create_from_int_has_INT_value_type() { assertThat(INT_MEASURE.getValueType()).isEqualTo(ValueType.INT); } @Test - public void create_from_long_has_LONG_value_type() { + void create_from_long_has_LONG_value_type() { assertThat(LONG_MEASURE.getValueType()).isEqualTo(ValueType.LONG); } @Test - public void create_from_double_has_DOUBLE_value_type() { + void create_from_double_has_DOUBLE_value_type() { assertThat(DOUBLE_MEASURE.getValueType()).isEqualTo(ValueType.DOUBLE); } @Test - public void create_from_boolean_has_BOOLEAN_value_type() { + void create_from_boolean_has_BOOLEAN_value_type() { assertThat(TRUE_MEASURE.getValueType()).isEqualTo(ValueType.BOOLEAN); assertThat(FALSE_MEASURE.getValueType()).isEqualTo(ValueType.BOOLEAN); } @Test - public void create_from_String_has_STRING_value_type() { + void create_from_String_has_STRING_value_type() { assertThat(STRING_MEASURE.getValueType()).isEqualTo(ValueType.STRING); } - @Test - @UseDataProvider("all_but_INT_MEASURE") - public void getIntValue_throws_ISE_for_all_value_types_except_INT(Measure measure) { + @ParameterizedTest + @MethodSource("all_but_INT_MEASURE") + void getIntValue_throws_ISE_for_all_value_types_except_INT(Measure measure) { assertThatThrownBy(measure::getIntValue) .isInstanceOf(IllegalStateException.class); } @Test - public void getIntValue_returns_value_for_INT_value_type() { + void getIntValue_returns_value_for_INT_value_type() { assertThat(INT_MEASURE.getIntValue()).isOne(); } - @Test - @UseDataProvider("all_but_LONG_MEASURE") - public void getLongValue_throws_ISE_for_all_value_types_except_LONG(Measure measure) { + @ParameterizedTest + @MethodSource("all_but_LONG_MEASURE") + void getLongValue_throws_ISE_for_all_value_types_except_LONG(Measure measure) { assertThatThrownBy(measure::getLongValue) .isInstanceOf(IllegalStateException.class); } @Test - public void getLongValue_returns_value_for_LONG_value_type() { + void getLongValue_returns_value_for_LONG_value_type() { assertThat(LONG_MEASURE.getLongValue()).isOne(); } - @Test - @UseDataProvider("all_but_DOUBLE_MEASURE") - public void getDoubleValue_throws_ISE_for_all_value_types_except_DOUBLE(Measure measure) { + @ParameterizedTest + @MethodSource("all_but_DOUBLE_MEASURE") + void getDoubleValue_throws_ISE_for_all_value_types_except_DOUBLE(Measure measure) { assertThatThrownBy(measure::getDoubleValue) .isInstanceOf(IllegalStateException.class); } @Test - public void getDoubleValue_returns_value_for_DOUBLE_value_type() { + void getDoubleValue_returns_value_for_DOUBLE_value_type() { assertThat(DOUBLE_MEASURE.getDoubleValue()).isEqualTo(1d); } - @Test - @UseDataProvider("all_but_BOOLEAN_MEASURE") - public void getBooleanValue_throws_ISE_for_all_value_types_except_BOOLEAN(Measure measure) { + @ParameterizedTest + @MethodSource("all_but_BOOLEAN_MEASURE") + void getBooleanValue_throws_ISE_for_all_value_types_except_BOOLEAN(Measure measure) { assertThatThrownBy(measure::getBooleanValue) .isInstanceOf(IllegalStateException.class); } @Test - public void getBooleanValue_returns_value_for_BOOLEAN_value_type() { + void getBooleanValue_returns_value_for_BOOLEAN_value_type() { assertThat(TRUE_MEASURE.getBooleanValue()).isTrue(); assertThat(FALSE_MEASURE.getBooleanValue()).isFalse(); } - @Test - @UseDataProvider("all_but_STRING_MEASURE") - public void getStringValue_throws_ISE_for_all_value_types_except_STRING(Measure measure) { + @ParameterizedTest + @MethodSource("all_but_STRING_MEASURE") + void getStringValue_throws_ISE_for_all_value_types_except_STRING(Measure measure) { assertThatThrownBy(measure::getStringValue) .isInstanceOf(IllegalStateException.class); } - @Test - @UseDataProvider("all_but_LEVEL_MEASURE") - public void getLevelValue_throws_ISE_for_all_value_types_except_LEVEL(Measure measure) { + @ParameterizedTest + @MethodSource("all_but_LEVEL_MEASURE") + void getLevelValue_throws_ISE_for_all_value_types_except_LEVEL(Measure measure) { assertThatThrownBy(measure::getLevelValue) .isInstanceOf(IllegalStateException.class); } @Test - public void getData_returns_null_for_NO_VALUE_value_type() { + void getData_returns_null_for_NO_VALUE_value_type() { assertThat(NO_VALUE_MEASURE.getData()).isNull(); } - @Test - @UseDataProvider("all_but_STRING_MEASURE") - public void getData_returns_null_for_all_value_types_but_STRING_when_not_set(Measure measure) { + @ParameterizedTest + @MethodSource("all_but_STRING_MEASURE") + void getData_returns_null_for_all_value_types_but_STRING_when_not_set(Measure measure) { assertThat(measure.getData()).isNull(); } @Test - public void getData_returns_value_for_STRING_value_type() { + void getData_returns_value_for_STRING_value_type() { assertThat(STRING_MEASURE.getData()).isEqualTo(STRING_MEASURE.getStringValue()); } - @Test - @UseDataProvider("all") - public void hasAlertStatus_returns_false_for_all_value_types_when_not_set(Measure measure) { + @ParameterizedTest + @MethodSource("all") + void hasAlertStatus_returns_false_for_all_value_types_when_not_set(Measure measure) { assertThat(measure.hasQualityGateStatus()).isFalse(); } - @Test - @UseDataProvider("all") - public void getAlertStatus_throws_ISE_for_all_value_types_when_not_set(Measure measure) { + @ParameterizedTest + @MethodSource("all") + void getAlertStatus_throws_ISE_for_all_value_types_when_not_set(Measure measure) { assertThatThrownBy(measure::getQualityGateStatus) .isInstanceOf(IllegalStateException.class); } @Test - public void getAlertStatus_returns_argument_from_setQualityGateStatus() { + void getAlertStatus_returns_argument_from_setQualityGateStatus() { QualityGateStatus someStatus = new QualityGateStatus(Measure.Level.OK); assertThat(newMeasureBuilder().setQualityGateStatus(someStatus).create(true, null).getQualityGateStatus()).isEqualTo(someStatus); @@ -229,13 +228,13 @@ public class MeasureTest { } @Test - public void newMeasureBuilder_setQualityGateStatus_throws_NPE_if_arg_is_null() { + void newMeasureBuilder_setQualityGateStatus_throws_NPE_if_arg_is_null() { assertThatThrownBy(() -> newMeasureBuilder().setQualityGateStatus(null)) .isInstanceOf(NullPointerException.class); } @Test - public void updateMeasureBuilder_setQualityGateStatus_throws_NPE_if_arg_is_null() { + void updateMeasureBuilder_setQualityGateStatus_throws_NPE_if_arg_is_null() { assertThatThrownBy(() -> { Measure.updatedMeasureBuilder(newMeasureBuilder().createNoValue()).setQualityGateStatus(null); }) @@ -243,7 +242,7 @@ public class MeasureTest { } @Test - public void updateMeasureBuilder_setQualityGateStatus_throws_USO_if_measure_already_has_a_QualityGateStatus() { + void updateMeasureBuilder_setQualityGateStatus_throws_USO_if_measure_already_has_a_QualityGateStatus() { assertThatThrownBy(() -> { QualityGateStatus qualityGateStatus = new QualityGateStatus(Measure.Level.ERROR); Measure.updatedMeasureBuilder(newMeasureBuilder().setQualityGateStatus(qualityGateStatus).createNoValue()).setQualityGateStatus(qualityGateStatus); @@ -251,9 +250,9 @@ public class MeasureTest { .isInstanceOf(UnsupportedOperationException.class); } - @Test - @UseDataProvider("all") - public void updateMeasureBuilder_creates_Measure_with_same_immutable_properties(Measure measure) { + @ParameterizedTest + @MethodSource("all") + void updateMeasureBuilder_creates_Measure_with_same_immutable_properties(Measure measure) { Measure newMeasure = Measure.updatedMeasureBuilder(measure).create(); assertThat(newMeasure.getValueType()).isEqualTo(measure.getValueType()); @@ -261,7 +260,7 @@ public class MeasureTest { } @Test - public void getData_returns_argument_from_factory_method() { + void getData_returns_argument_from_factory_method() { String someData = "lololool"; assertThat(newMeasureBuilder().create(true, someData).getData()).isEqualTo(someData); @@ -272,12 +271,12 @@ public class MeasureTest { } @Test - public void measure_of_value_type_LEVEL_has_no_data() { + void measure_of_value_type_LEVEL_has_no_data() { assertThat(LEVEL_MEASURE.getData()).isNull(); } @Test - public void double_values_are_scaled_to_1_digit_and_round() { + void double_values_are_scaled_to_1_digit_and_round() { assertThat(newMeasureBuilder().create(30.27777d, 1).getDoubleValue()).isEqualTo(30.3d); assertThat(newMeasureBuilder().create(30d, 1).getDoubleValue()).isEqualTo(30d); assertThat(newMeasureBuilder().create(30.01d, 1).getDoubleValue()).isEqualTo(30d); @@ -285,21 +284,21 @@ public class MeasureTest { } @Test - public void create_with_double_value_throws_IAE_if_value_is_NaN() { + void create_with_double_value_throws_IAE_if_value_is_NaN() { assertThatThrownBy(() -> newMeasureBuilder().create(Double.NaN, 1)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("NaN is not allowed as a Measure value"); } @Test - public void create_with_double_value_data_throws_IAE_if_value_is_NaN() { + void create_with_double_value_data_throws_IAE_if_value_is_NaN() { assertThatThrownBy(() -> newMeasureBuilder().create(Double.NaN, 1, "some data")) .isInstanceOf(IllegalArgumentException.class) .hasMessage("NaN is not allowed as a Measure value"); } @Test - public void valueMeasureImplEquals_instanceNotEqualToNull() { + void valueMeasureImplEquals_instanceNotEqualToNull() { Measure.ValueMeasureImpl valueMeasureImpl = (Measure.ValueMeasureImpl) new Measure.NewMeasureBuilder().create(0, null); boolean equal = valueMeasureImpl.equals(null); @@ -308,7 +307,7 @@ public class MeasureTest { } @Test - public void valueMeasureImplEquals_sameInstance_returnTrue() { + void valueMeasureImplEquals_sameInstance_returnTrue() { Measure.ValueMeasureImpl valueMeasureImpl = (Measure.ValueMeasureImpl) new Measure.NewMeasureBuilder().create(0, null); boolean equal = valueMeasureImpl.equals(valueMeasureImpl); @@ -316,4 +315,66 @@ public class MeasureTest { assertThat(equal).isTrue(); } + @Test + void create_with_metric_and_no_value_returns_no_value_measure() { + assertThat(new Measure.NewMeasureBuilder().create(INT_METRIC, null).getValueType()).isEqualTo(ValueType.NO_VALUE); + } + + @Test + void create_with_metric_and_invalid_level_returns_no_value_measure() { + assertThat(new Measure.NewMeasureBuilder().create(LEVEL_METRIC, "invalid_level").getValueType()).isEqualTo(ValueType.NO_VALUE); + } + + @Test + void create_with_level_metric_returns_level_measure() { + Measure measure = new Measure.NewMeasureBuilder().create(LEVEL_METRIC, "OK"); + assertThat(measure.getValueType()).isEqualTo(ValueType.LEVEL); + assertThat(measure.getLevelValue()).isEqualTo(Measure.Level.OK); + } + + @Test + void create_with_string_metric_returns_string_measure() { + Measure measure = new Measure.NewMeasureBuilder().create(STRING_METRIC, "sample"); + assertThat(measure.getValueType()).isEqualTo(ValueType.STRING); + assertThat(measure.getStringValue()).isEqualTo("sample"); + assertThat(measure.getData()).isEqualTo("sample"); + } + + @Test + void create_with_int_metric_returns_int_measure() { + Measure measure = new Measure.NewMeasureBuilder().create(INT_METRIC, 1.5d); + assertThat(measure.getValueType()).isEqualTo(ValueType.INT); + assertThat(measure.getIntValue()).isEqualTo(1); + } + + @Test + void create_with_long_metric_returns_long_measure() { + Measure measure = new Measure.NewMeasureBuilder().create(LONG_METRIC, 1.5d); + assertThat(measure.getValueType()).isEqualTo(ValueType.LONG); + assertThat(measure.getLongValue()).isEqualTo(1L); + } + + @Test + void create_with_double_metric_returns_long_measure() { + Measure measure = new Measure.NewMeasureBuilder().create(DOUBLE_METRIC, 0.12345); + assertThat(measure.getValueType()).isEqualTo(ValueType.DOUBLE); + assertThat(measure.getDoubleValue()).isEqualTo(0.12345); + } + + @ParameterizedTest + @MethodSource("boolean_measure_values") + void create_with_boolean_metric_returns_boolean_measure(Double value, boolean expected) { + Measure measure = new Measure.NewMeasureBuilder().create(BOOLEAN_METRIC, value); + assertThat(measure.getValueType()).isEqualTo(ValueType.BOOLEAN); + assertThat(measure.getBooleanValue()).isEqualTo(expected); + } + + private static Stream<Arguments> boolean_measure_values() { + return Stream.of( + Arguments.of(1.0, true), + Arguments.of(0.0, false), + Arguments.of(0.5, false), + Arguments.of(1.5, false) + ); + } } diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/measure/LiveMeasureDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/measure/LiveMeasureDaoIT.java index ae7852e6607..6b2796b348c 100644 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/measure/LiveMeasureDaoIT.java +++ b/server/sonar-db-dao/src/it/java/org/sonar/db/measure/LiveMeasureDaoIT.java @@ -31,7 +31,6 @@ import org.apache.commons.lang3.RandomStringUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import org.mockito.internal.util.collections.Sets; import org.sonar.api.utils.System2; import org.sonar.db.DbTester; import org.sonar.db.component.BranchDto; @@ -42,17 +41,12 @@ import org.sonar.db.metric.MetricDto; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; -import static java.util.Collections.singleton; import static java.util.Collections.singletonList; -import static java.util.function.Function.identity; -import static java.util.stream.Collectors.toMap; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.groups.Tuple.tuple; import static org.sonar.api.measures.Metric.ValueType.DATA; import static org.sonar.api.measures.Metric.ValueType.INT; -import static org.sonar.db.component.BranchDto.DEFAULT_MAIN_BRANCH_NAME; import static org.sonar.db.component.ComponentTesting.newFileDto; -import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; import static org.sonar.db.measure.MeasureTesting.newLiveMeasure; class LiveMeasureDaoIT { @@ -116,120 +110,6 @@ class LiveMeasureDaoIT { } @Test - void selectByComponentUuidsAndMetricKeys() { - LiveMeasureDto measure1 = newLiveMeasure().setMetricUuid(metric.getUuid()); - LiveMeasureDto measure2 = newLiveMeasure().setMetricUuid(metric.getUuid()); - underTest.insert(db.getSession(), measure1); - underTest.insert(db.getSession(), measure2); - - List<LiveMeasureDto> selected = underTest.selectByComponentUuidsAndMetricKeys(db.getSession(), asList(measure1.getComponentUuid(), - measure2.getComponentUuid()), - singletonList(metric.getKey())); - assertThat(selected) - .extracting(LiveMeasureDto::getComponentUuid, LiveMeasureDto::getProjectUuid, LiveMeasureDto::getMetricUuid, - LiveMeasureDto::getValue, LiveMeasureDto::getDataAsString) - .containsExactlyInAnyOrder( - tuple(measure1.getComponentUuid(), measure1.getProjectUuid(), measure1.getMetricUuid(), measure1.getValue(), - measure1.getDataAsString()), - tuple(measure2.getComponentUuid(), measure2.getProjectUuid(), measure2.getMetricUuid(), measure2.getValue(), - measure2.getDataAsString())); - - assertThat(underTest.selectByComponentUuidsAndMetricKeys(db.getSession(), emptyList(), singletonList(metric.getKey()))).isEmpty(); - assertThat(underTest.selectByComponentUuidsAndMetricKeys(db.getSession(), singletonList(measure1.getComponentUuid()), emptyList())).isEmpty(); - } - - @Test - void selectByComponentUuidsAndMetricKeys_returns_empty_list_if_metric_does_not_match() { - LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid()); - underTest.insert(db.getSession(), measure); - - List<LiveMeasureDto> selected = underTest.selectByComponentUuidsAndMetricKeys(db.getSession(), - singletonList(measure.getComponentUuid()), singletonList("_other_")); - - assertThat(selected).isEmpty(); - } - - @Test - void selectByComponentUuidsAndMetricKeys_returns_empty_list_if_component_does_not_match() { - LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid()); - underTest.insert(db.getSession(), measure); - - List<LiveMeasureDto> selected = underTest.selectByComponentUuidsAndMetricKeys(db.getSession(), singletonList("_missing_"), - singletonList(metric.getKey())); - - assertThat(selected).isEmpty(); - } - - @Test - void selectForProjectsByMetricUuids() { - MetricDto metric = db.measures().insertMetric(); - MetricDto metric2 = db.measures().insertMetric(); - BranchDto projectBranch = db.components().insertPrivateProject().getMainBranchDto(); - BranchDto project2Branch = db.components().insertPrivateProject().getMainBranchDto(); - underTest.insert(db.getSession(), newLiveMeasure(projectBranch, metric).setValue(3.14).setData((String) null)); - underTest.insert(db.getSession(), newLiveMeasure(projectBranch, metric2).setValue(4.54).setData((String) null)); - underTest.insert(db.getSession(), newLiveMeasure(project2Branch, metric).setValue(99.99).setData((String) null)); - - List<ProjectMainBranchLiveMeasureDto> selected = underTest.selectForProjectMainBranchesByMetricUuids(db.getSession(), - List.of(metric.getUuid(), metric2.getUuid())); - assertThat(selected) - .extracting(ProjectMainBranchLiveMeasureDto::getProjectUuid, ProjectMainBranchLiveMeasureDto::getMetricUuid, - ProjectMainBranchLiveMeasureDto::getValue, ProjectMainBranchLiveMeasureDto::getTextValue) - .containsExactlyInAnyOrder( - tuple(projectBranch.getProjectUuid(), metric.getUuid(), 3.14, null), - tuple(projectBranch.getProjectUuid(), metric2.getUuid(), 4.54, null), - tuple(project2Branch.getProjectUuid(), metric.getUuid(), 99.99, null)); - } - - @Test - void selectForProjectMainBranchesByMetricUuids_whenMultipleBranches_shouldRetrieveMetricsFromMainBranch() { - MetricDto metric = db.measures().insertMetric(); - ProjectData projectData = db.components().insertPrivateProject(); - BranchDto mainBranch = projectData.getMainBranchDto(); - BranchDto branch1 = db.components().insertProjectBranch(projectData.getProjectDto()); - BranchDto branch2 = db.components().insertProjectBranch(projectData.getProjectDto()); - underTest.insert(db.getSession(), newLiveMeasure(mainBranch, metric).setValue(3.14).setData((String) null)); - underTest.insert(db.getSession(), newLiveMeasure(branch1, metric).setValue(4.54).setData((String) null)); - underTest.insert(db.getSession(), newLiveMeasure(branch2, metric).setValue(99.99).setData((String) null)); - - List<ProjectMainBranchLiveMeasureDto> selected = underTest.selectForProjectMainBranchesByMetricUuids(db.getSession(), - List.of(metric.getUuid())); - assertThat(selected) - .extracting(ProjectMainBranchLiveMeasureDto::getProjectUuid, ProjectMainBranchLiveMeasureDto::getMetricUuid, - ProjectMainBranchLiveMeasureDto::getValue, ProjectMainBranchLiveMeasureDto::getTextValue) - .containsExactlyInAnyOrder( - tuple(mainBranch.getProjectUuid(), metric.getUuid(), 3.14, null)); - } - - @Test - void selectForProjectsByMetricUuids_whenMetricDoesNotMatch_shouldReturnEmptyList() { - ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); - underTest.insert(db.getSession(), newLiveMeasure(project, metric).setValue(3.14).setData((String) null)); - List<ProjectMainBranchLiveMeasureDto> selected = underTest.selectForProjectMainBranchesByMetricUuids(db.getSession(), singletonList( - "_other_")); - assertThat(selected).isEmpty(); - } - - @Test - void selectForProjectsByMetricUuids_shouldReturnProjectWithTRKQualifierOnly() { - MetricDto metric = db.measures().insertMetric(); - ProjectData application = db.components().insertPrivateApplication(); - ProjectData project = db.components().insertPrivateProject(); - ProjectData project2 = db.components().insertPrivateProject(); - db.components().addApplicationProject(application, project, project2); - underTest.insert(db.getSession(), newLiveMeasure(application.getMainBranchComponent(), metric).setValue(3.14).setData((String) null)); - underTest.insert(db.getSession(), newLiveMeasure(project.getMainBranchComponent(), metric).setValue(4.54).setData((String) null)); - underTest.insert(db.getSession(), newLiveMeasure(project2.getMainBranchComponent(), metric).setValue(5.56).setData((String) null)); - - List<ProjectMainBranchLiveMeasureDto> selected = underTest.selectForProjectMainBranchesByMetricUuids(db.getSession(), - List.of(metric.getUuid())); - - assertThat(selected) - .extracting(ProjectMainBranchLiveMeasureDto::getProjectUuid) - .containsExactlyInAnyOrder(project.projectUuid(), project2.projectUuid()); - } - - @Test void selectByComponentUuidAndMetricKey() { LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid()); underTest.insert(db.getSession(), measure); @@ -257,40 +137,6 @@ class LiveMeasureDaoIT { } @Test - void selectByComponentUuidAndMetricKeys() { - MetricDto metric2 = db.measures().insertMetric(); - - LiveMeasureDto measure1 = newLiveMeasure().setMetricUuid(metric.getUuid()).setValue(1.0).setComponentUuid("uuid"); - LiveMeasureDto measure2 = newLiveMeasure().setMetricUuid(metric2.getUuid()).setValue(2.0).setComponentUuid("uuid"); - - underTest.insert(db.getSession(), measure1); - underTest.insert(db.getSession(), measure2); - - List<LiveMeasureDto> selected = underTest.selectByComponentUuidAndMetricKeys(db.getSession(), "uuid", asList(metric.getKey(), - metric2.getKey())); - - assertThat(selected).hasSize(2); - assertThat(selected).extracting(LiveMeasureDto::getMetricUuid, LiveMeasureDto::getValue) - .containsExactlyInAnyOrder(tuple(metric.getUuid(), measure1.getValue()), tuple(metric2.getUuid(), measure2.getValue())); - } - - @Test - void selectByComponentUuidAndMetricKeys_return_empty_if_component_does_not_match() { - LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid()); - underTest.insert(db.getSession(), measure); - - assertThat(underTest.selectByComponentUuidAndMetricKeys(db.getSession(), "_missing_", singletonList(metric.getKey()))).isEmpty(); - } - - @Test - void selectByComponentUuidAndMetricKeys_return_empty_if_no_metric_matches() { - LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid()); - underTest.insert(db.getSession(), measure); - - assertThat(underTest.selectByComponentUuidAndMetricKeys(db.getSession(), measure.getComponentUuid(), singletonList("_missing_"))).isEmpty(); - } - - @Test void selectMeasure() { MetricDto metric = db.measures().insertMetric(); LiveMeasureDto stored = newLiveMeasure().setMetricUuid(metric.getUuid()); @@ -311,71 +157,6 @@ class LiveMeasureDaoIT { } @Test - void selectTreeByQuery() { - List<LiveMeasureDto> results = new ArrayList<>(); - MetricDto metric = db.measures().insertMetric(); - ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); - ComponentDto file = db.components().insertComponent(newFileDto(project)); - underTest.insert(db.getSession(), newLiveMeasure(file, metric).setValue(3.14)); - - underTest.selectTreeByQuery(db.getSession(), project, - MeasureTreeQuery.builder() - .setMetricUuids(singleton(metric.getUuid())) - .setStrategy(MeasureTreeQuery.Strategy.LEAVES).build(), - context -> results.add(context.getResultObject())); - - assertThat(results).hasSize(1); - LiveMeasureDto result = results.get(0); - assertThat(result.getComponentUuid()).isEqualTo(file.uuid()); - assertThat(result.getMetricUuid()).isEqualTo(metric.getUuid()); - assertThat(result.getValue()).isEqualTo(3.14); - } - - @Test - void scrollSelectByComponentUuidAndMetricKeys_for_non_empty_metric_set() { - List<LiveMeasureDto> results = new ArrayList<>(); - MetricDto metric = db.measures().insertMetric(); - MetricDto metric2 = db.measures().insertMetric(); - ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); - ComponentDto project2 = db.components().insertPrivateProject().getMainBranchComponent(); - underTest.insert(db.getSession(), newLiveMeasure(project, metric).setValue(3.14)); - underTest.insert(db.getSession(), newLiveMeasure(project, metric2).setValue(4.54)); - underTest.insert(db.getSession(), newLiveMeasure(project2, metric).setValue(99.99)); - underTest.scrollSelectByComponentUuidAndMetricKeys(db.getSession(), project.uuid(), Sets.newSet(metric.getKey(), metric2.getKey()), - context -> results.add(context.getResultObject())); - - assertThat(results).hasSize(2); - LiveMeasureDto result = results.stream().filter(lm -> lm.getMetricUuid().equals(metric.getUuid())).findFirst().get(); - assertThat(result.getComponentUuid()).isEqualTo(project.uuid()); - assertThat(result.getMetricUuid()).isEqualTo(metric.getUuid()); - assertThat(result.getValue()).isEqualTo(3.14); - LiveMeasureDto result2 = results.stream().filter(lm -> lm.getMetricUuid().equals(metric2.getUuid())).findFirst().get(); - assertThat(result2.getComponentUuid()).isEqualTo(project.uuid()); - assertThat(result2.getMetricUuid()).isEqualTo(metric2.getUuid()); - assertThat(result2.getValue()).isEqualTo(4.54); - } - - @Test - void scrollSelectByComponentUuidAndMetricKeys_for_empty_metric_set() { - List<LiveMeasureDto> results = new ArrayList<>(); - ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); - underTest.scrollSelectByComponentUuidAndMetricKeys(db.getSession(), project.uuid(), Sets.newSet(), - context -> results.add(context.getResultObject())); - - assertThat(results).isEmpty(); - } - - @Test - void selectTreeByQuery_with_empty_results() { - List<LiveMeasureDto> results = new ArrayList<>(); - underTest.selectTreeByQuery(db.getSession(), newPrivateProjectDto(), - MeasureTreeQuery.builder().setStrategy(MeasureTreeQuery.Strategy.LEAVES).build(), - context -> results.add(context.getResultObject())); - - assertThat(results).isEmpty(); - } - - @Test void selectMeasure_map_fields() { MetricDto metric = db.measures().insertMetric(); ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); @@ -393,92 +174,6 @@ class LiveMeasureDaoIT { } @Test - void countNcloc() { - MetricDto ncloc = db.measures().insertMetric(m -> m.setKey("ncloc").setValueType(INT.toString())); - MetricDto lines = db.measures().insertMetric(m -> m.setKey("lines").setValueType(INT.toString())); - - ProjectData simpleProject = db.components().insertPublicProject(); - db.measures().insertLiveMeasure(simpleProject, ncloc, m -> m.setValue(10d)); - - ProjectData projectWithBiggerBranch = db.components().insertPublicProject(); - BranchDto bigBranch = db.components().insertProjectBranch(projectWithBiggerBranch.getProjectDto(), - b -> b.setBranchType(BranchType.BRANCH)); - db.measures().insertLiveMeasure(projectWithBiggerBranch, ncloc, m -> m.setValue(100d)); - db.measures().insertLiveMeasure(bigBranch, ncloc, m -> m.setValue(200d)); - - ProjectData projectWithLinesButNoLoc = db.components().insertPublicProject(); - db.measures().insertLiveMeasure(projectWithLinesButNoLoc, lines, m -> m.setValue(365d)); - db.measures().insertLiveMeasure(projectWithLinesButNoLoc, ncloc, m -> m.setValue(0d)); - - assertThat(underTest.findNclocOfBiggestBranchForProject(db.getSession(), simpleProject.projectUuid())).isEqualTo(10L); - assertThat(underTest.findNclocOfBiggestBranchForProject(db.getSession(), projectWithBiggerBranch.projectUuid())).isEqualTo(200L); - assertThat(underTest.findNclocOfBiggestBranchForProject(db.getSession(), projectWithLinesButNoLoc.projectUuid())).isZero(); - } - - @Test - void get_branch_with_max_ncloc_per_project() { - Map<String, MetricDto> metrics = setupMetrics(); - MetricDto ncloc = metrics.get("ncloc"); - setupProjectsWithLoc(ncloc, metrics.get("ncloc_language_distribution"), metrics.get("lines")); - - Map<String, LargestBranchNclocDto> results = underTest.getLargestBranchNclocPerProject(db.getSession(), ncloc.getUuid()) - .stream() - .collect(toMap(largestBranchNclocDto -> largestBranchNclocDto.getProjectKey() + " " + largestBranchNclocDto.getBranchName(), - identity(), (a, b) -> a)); - - assertThat(results).hasSize(5); - assertLocForProject(results.get("projectWithTieOnBranchSize main"), DEFAULT_MAIN_BRANCH_NAME, 250); - assertLocForProject(results.get("projectWithTieOnOtherBranches tieBranch1"), "tieBranch1", 230); - assertLocForProject(results.get("projectWithBranchBiggerThanMaster notMasterBranch"), "notMasterBranch", 200); - assertLocForProject(results.get("simpleProject main"), DEFAULT_MAIN_BRANCH_NAME, 10); - assertLocForProject(results.get("projectWithLinesButNoLoc main"), DEFAULT_MAIN_BRANCH_NAME, 0); - } - - @Test - void get_loc_language_distribution() { - Map<String, MetricDto> metrics = setupMetrics(); - MetricDto ncloc = metrics.get("ncloc"); - MetricDto nclocLanguageDistribution = metrics.get("ncloc_language_distribution"); - setupProjectsWithLoc(ncloc, nclocLanguageDistribution, metrics.get("lines")); - - List<ProjectLocDistributionDto> results = underTest.selectLargestBranchesLocDistribution(db.getSession(), ncloc.getUuid(), - nclocLanguageDistribution.getUuid()); - - String firstBranchOfProjectUuid = - db.getDbClient().branchDao().selectByProjectUuid(db.getSession(), "projectWithTieOnOtherBranches").stream() - .filter(branchDto -> !branchDto.isMain()) - .map(BranchDto::getUuid) - .sorted() - .findFirst().orElseThrow(); - - assertThat(results) - .containsExactlyInAnyOrder( - new ProjectLocDistributionDto("projectWithTieOnBranchSize", getMainBranchUuid("projectWithTieOnBranchSize"), "java=250;js=0"), - new ProjectLocDistributionDto("projectWithTieOnOtherBranches", firstBranchOfProjectUuid, "java=230;js=0"), - new ProjectLocDistributionDto("projectWithBranchBiggerThanMaster", getBranchUuid("projectWithBranchBiggerThanMaster", - "notMasterBranch"), "java=100;js=100"), - new ProjectLocDistributionDto("simpleProject", getMainBranchUuid("simpleProject"), "java=10;js=0"), - new ProjectLocDistributionDto("projectWithLinesButNoLoc", getMainBranchUuid("projectWithLinesButNoLoc"), "java=0;js=0")); - } - - private String getBranchUuid(String projectUuid, String branchKey) { - return db.getDbClient().branchDao().selectByBranchKey(db.getSession(), projectUuid, branchKey).get().getUuid(); - } - - private String getMainBranchUuid(String projectUuid) { - return db.getDbClient().branchDao().selectMainBranchByProjectUuid(db.getSession(), projectUuid).get().getUuid(); - } - - @Test - void countNcloc_empty() { - db.measures().insertMetric(m -> m.setKey("ncloc").setValueType(INT.toString())); - db.measures().insertMetric(m -> m.setKey("lines").setValueType(INT.toString())); - long result = underTest.findNclocOfBiggestBranchForProject(db.getSession(), "non-existing-project-uuid"); - - assertThat(result).isZero(); - } - - @Test void insert_data() { byte[] data = "text_value".getBytes(StandardCharsets.UTF_8); MetricDto metric = db.measures().insertMetric(); @@ -531,23 +226,6 @@ class LiveMeasureDaoIT { } @Test - void deleteByComponentUuid() { - LiveMeasureDto measure1 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("1"); - LiveMeasureDto measure2 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("2"); - LiveMeasureDto measure3 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("3"); - LiveMeasureDto measureOtherComponent = newLiveMeasure().setComponentUuid("C2").setMetricUuid("3"); - underTest.insertOrUpdate(db.getSession(), measure1); - underTest.insertOrUpdate(db.getSession(), measure2); - underTest.insertOrUpdate(db.getSession(), measure3); - underTest.insertOrUpdate(db.getSession(), measureOtherComponent); - - underTest.deleteByComponent(db.getSession(), "C1"); - - verifyTableSize(1); - verifyPersisted(measureOtherComponent); - } - - @Test void deleteByComponentUuidExcludingMetricUuids_with_empty_metrics() { LiveMeasureDto measure1 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("1"); LiveMeasureDto measure2 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("2"); @@ -563,21 +241,6 @@ class LiveMeasureDaoIT { } @Test - void countProjectsHavingMeasure() { - MetricDto metric1 = db.measures().insertMetric(); - MetricDto metric2 = db.measures().insertMetric(); - ComponentDto project1 = db.components().insertPrivateProject().getMainBranchComponent(); - ComponentDto project2 = db.components().insertPrivateProject().getMainBranchComponent(); - db.measures().insertLiveMeasure(project1, metric1); - db.measures().insertLiveMeasure(project2, metric1); - db.measures().insertLiveMeasure(project1, metric2); - - assertThat(underTest.countProjectsHavingMeasure(db.getSession(), metric1.getKey())).isEqualTo(2); - assertThat(underTest.countProjectsHavingMeasure(db.getSession(), metric2.getKey())).isOne(); - assertThat(underTest.countProjectsHavingMeasure(db.getSession(), "unknown")).isZero(); - } - - @Test void upsert_inserts_or_updates_row() { if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) { return; @@ -753,74 +416,4 @@ class LiveMeasureDaoIT { // do not compare the field "uuid", which is used only for insert, not select "componentUuid", "projectUuid", "metricUuid", "value", "textValue", "data"); } - - private Map<String, MetricDto> setupMetrics() { - MetricDto ncloc = db.measures().insertMetric(m -> m.setKey("ncloc").setValueType(INT.toString())); - MetricDto nclocDistribution = db.measures().insertMetric(m -> m.setKey("ncloc_language_distribution").setValueType(DATA.toString())); - MetricDto lines = db.measures().insertMetric(m -> m.setKey("lines").setValueType(INT.toString())); - return Map.of("ncloc", ncloc, - "ncloc_language_distribution", nclocDistribution, - "lines", lines); - } - - private void setupProjectsWithLoc(MetricDto ncloc, MetricDto nclocDistribution, MetricDto lines) { - ProjectData simpleProject = addProjectWithMeasure("simpleProject", ncloc, 10d); - addMeasureToMainBranch(simpleProject, nclocDistribution, "java=10;js=0"); - - ProjectData projectWithBranchBiggerThanMaster = addProjectWithMeasure("projectWithBranchBiggerThanMaster", ncloc, 100d); - addMeasureToMainBranch(projectWithBranchBiggerThanMaster, nclocDistribution, "java=100;js=0"); - - BranchDto notMasterBranch = addBranchToProjectWithMeasure(projectWithBranchBiggerThanMaster, "notMasterBranch", ncloc, 200d); - addMeasureToBranch(notMasterBranch, nclocDistribution, "java=100;js=100"); - - ProjectData projectWithLinesButNoLoc = addProjectWithMeasure("projectWithLinesButNoLoc", lines, 365d); - addMeasureToMainBranch(projectWithLinesButNoLoc, nclocDistribution, "java=0;js=0"); - addMeasureToBranch(projectWithLinesButNoLoc.getMainBranchDto(), ncloc, 0d, false); - - ProjectData projectWithTieOnBranchSize = addProjectWithMeasure("projectWithTieOnBranchSize", ncloc, 250d); - addMeasureToMainBranch(projectWithTieOnBranchSize, nclocDistribution, "java=250;js=0"); - BranchDto tieBranch = addBranchToProjectWithMeasure(projectWithTieOnBranchSize, "tieBranch", ncloc, 250d); - addMeasureToBranch(tieBranch, nclocDistribution, "java=250;js=0"); - - ProjectData projectWithTieOnOtherBranches = addProjectWithMeasure("projectWithTieOnOtherBranches", ncloc, 220d); - addMeasureToMainBranch(projectWithTieOnOtherBranches, nclocDistribution, "java=220;js=0"); - BranchDto tieBranch1 = addBranchToProjectWithMeasure(projectWithTieOnOtherBranches, "tieBranch1", ncloc, 230d); - addMeasureToBranch(tieBranch1, nclocDistribution, "java=230;js=0"); - BranchDto tieBranch2 = addBranchToProjectWithMeasure(projectWithTieOnOtherBranches, "tieBranch2", ncloc, 230d); - addMeasureToBranch(tieBranch2, nclocDistribution, "java=230;js=0"); - } - - private ProjectData addProjectWithMeasure(String projectKey, MetricDto metric, double metricValue) { - ProjectData project = db.components().insertPublicProject(projectKey, p -> p.setKey(projectKey)); - addMeasureToBranch(project.getMainBranchDto(), metric, metricValue, true); - return project; - } - - private void addMeasureToBranch(BranchDto component, MetricDto metric, double metricValue, boolean addSnapshot) { - db.measures().insertLiveMeasure(component, metric, m -> m.setValue(metricValue)); - if (addSnapshot) { - db.components().insertSnapshot(component, t -> t.setLast(true)); - } - } - - private void addMeasureToMainBranch(ProjectData projectData, MetricDto metric, String metricValue) { - addMeasureToBranch(projectData.getMainBranchDto(), metric, metricValue); - } - - private void addMeasureToBranch(BranchDto component, MetricDto metric, String metricValue) { - db.measures().insertLiveMeasure(component, metric, m -> m.setData(metricValue)); - } - - private BranchDto addBranchToProjectWithMeasure(ProjectData project, String branchKey, MetricDto metric, double metricValue) { - BranchDto branch = db.components() - .insertProjectBranch(project.getProjectDto(), b -> b.setBranchType(BranchType.BRANCH).setKey(branchKey), - branchDto -> branchDto.setUuid("uuid_" + branchId++)); - addMeasureToBranch(branch, metric, metricValue, true); - return branch; - } - - private void assertLocForProject(LargestBranchNclocDto result, String branchKey, long linesOfCode) { - assertThat(result.getBranchName()).isEqualTo(branchKey); - assertThat(result.getLoc()).isEqualTo(linesOfCode); - } } diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/purge/PurgeDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/purge/PurgeDaoIT.java index 59c3dea76c3..56f593919df 100644 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/purge/PurgeDaoIT.java +++ b/server/sonar-db-dao/src/it/java/org/sonar/db/purge/PurgeDaoIT.java @@ -385,7 +385,7 @@ project.getProjectDto().getUuid()), PurgeListener.EMPTY, new PurgeProfiler()); // delete measures of selected assertThat(db.countRowsOfTable("measures")).isEqualTo(2); List<MeasureDto> measureDtos = Set.of(srcFile.uuid(), dir.uuid(), mainBranch.uuid(), enabledFile.uuid()).stream() - .map(component -> db.getDbClient().measureDao().selectMeasure(dbSession, component)) + .map(component -> db.getDbClient().measureDao().selectByComponentUuid(dbSession, component)) .filter(Optional::isPresent).map(Optional::get).toList(); assertThat(measureDtos) .extracting(MeasureDto::getComponentUuid) @@ -1737,10 +1737,10 @@ project.getProjectDto().getKey()); List.of(metric.getUuid()))).isEmpty(); assertThat(dbClient.liveMeasureDao().selectByComponentUuidsAndMetricUuids(dbSession, List.of(project2.uuid(), dir2.uuid()), List.of(metric.getUuid()))).hasSize(2); - assertThat(dbClient.measureDao().selectMeasure(dbSession, project1.uuid())).isEmpty(); - assertThat(dbClient.measureDao().selectMeasure(dbSession, dir1.uuid())).isEmpty(); - assertThat(dbClient.measureDao().selectMeasure(dbSession, project2.uuid())).isNotEmpty(); - assertThat(dbClient.measureDao().selectMeasure(dbSession, dir2.uuid())).isNotEmpty(); + assertThat(dbClient.measureDao().selectByComponentUuid(dbSession, project1.uuid())).isEmpty(); + assertThat(dbClient.measureDao().selectByComponentUuid(dbSession, dir1.uuid())).isEmpty(); + assertThat(dbClient.measureDao().selectByComponentUuid(dbSession, project2.uuid())).isNotEmpty(); + assertThat(dbClient.measureDao().selectByComponentUuid(dbSession, dir2.uuid())).isNotEmpty(); } private void verifyNoEffect(ComponentDto firstRoot, ComponentDto... otherRoots) { diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDao.java index 4cc2a2f1efb..be285e98e4a 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDao.java @@ -23,15 +23,12 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; -import org.apache.ibatis.session.ResultHandler; import org.sonar.api.utils.System2; import org.sonar.core.util.Uuids; import org.sonar.db.Dao; import org.sonar.db.DbSession; -import org.sonar.db.component.ComponentDto; import org.sonar.db.dialect.Dialect; -import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; import static org.sonar.db.DatabaseUtils.executeLargeInputs; public class LiveMeasureDao implements Dao { @@ -52,65 +49,11 @@ public class LiveMeasureDao implements Dao { componentUuids -> mapper(dbSession).selectByComponentUuidsAndMetricUuids(componentUuids, metricUuids)); } - public List<ProjectMainBranchLiveMeasureDto> selectForProjectMainBranchesByMetricUuids(DbSession dbSession, Collection<String> metricUuids) { - return mapper(dbSession).selectForProjectMainBranchesByMetricUuids(metricUuids); - } - - public void scrollSelectByComponentUuidAndMetricKeys(DbSession dbSession, String componentUuid, Collection<String> metricKeys, ResultHandler<LiveMeasureDto> handler) { - if (metricKeys.isEmpty()) { - return; - } - - mapper(dbSession).scrollSelectByComponentUuidAndMetricKeys(componentUuid, metricKeys, handler); - } - - public List<LiveMeasureDto> selectByComponentUuidsAndMetricKeys(DbSession dbSession, Collection<String> largeComponentUuids, Collection<String> metricKeys) { - if (largeComponentUuids.isEmpty() || metricKeys.isEmpty()) { - return Collections.emptyList(); - } - - return executeLargeInputs( - largeComponentUuids, - componentUuids -> mapper(dbSession).selectByComponentUuidsAndMetricKeys(componentUuids, metricKeys)); - } - - public List<LiveMeasureDto> selectByComponentUuidAndMetricKeys(DbSession dbSession, String componentUuid, Collection<String> metricKeys) { - if (metricKeys.isEmpty()) { - return Collections.emptyList(); - } - - return mapper(dbSession).selectByComponentUuidAndMetricKeys(componentUuid, metricKeys); - } - public Optional<LiveMeasureDto> selectMeasure(DbSession dbSession, String componentUuid, String metricKey) { LiveMeasureDto liveMeasureDto = mapper(dbSession).selectByComponentUuidAndMetricKey(componentUuid, metricKey); return Optional.ofNullable(liveMeasureDto); } - public void selectTreeByQuery(DbSession dbSession, ComponentDto baseComponent, MeasureTreeQuery query, ResultHandler<LiveMeasureDto> resultHandler) { - if (query.returnsEmpty()) { - return; - } - mapper(dbSession).selectTreeByQuery(query, baseComponent.uuid(), query.getUuidPath(baseComponent), resultHandler); - } - - public long findNclocOfBiggestBranchForProject(DbSession dbSession, String projectUuid){ - Long ncloc = mapper(dbSession).findNclocOfBiggestBranchForProject(projectUuid, NCLOC_KEY); - return ncloc == null ? 0L : ncloc; - } - - public List<LargestBranchNclocDto> getLargestBranchNclocPerProject(DbSession dbSession, String nclocMetricUuid) { - return mapper(dbSession).getLargestBranchNclocPerProject(nclocMetricUuid); - } - - public List<ProjectLocDistributionDto> selectLargestBranchesLocDistribution(DbSession session, String nclocUuid, String nclocDistributionUuid) { - return mapper(session).selectLargestBranchesLocDistribution(nclocUuid, nclocDistributionUuid); - } - - public long countProjectsHavingMeasure(DbSession dbSession, String metric) { - return mapper(dbSession).countProjectsHavingMeasure(metric); - } - public void insert(DbSession dbSession, LiveMeasureDto dto) { mapper(dbSession).insert(dto, Uuids.create(), system2.now()); } @@ -123,10 +66,6 @@ public class LiveMeasureDao implements Dao { } } - public void deleteByComponent(DbSession dbSession, String componentUuid) { - mapper(dbSession).deleteByComponent(componentUuid); - } - /** * Similar to {@link #insertOrUpdate(DbSession, LiveMeasureDto)}, except that it triggers a single SQL request * <strong>This method should not be called unless {@link Dialect#supportsUpsert()} is true</strong> diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureMapper.java index 5516a70e95f..691168ad52e 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureMapper.java @@ -31,42 +31,10 @@ public interface LiveMeasureMapper { @Param("componentUuids") Collection<String> componentUuids, @Param("metricUuids") Collection<String> metricUuids); - List<ProjectMainBranchLiveMeasureDto> selectForProjectMainBranchesByMetricUuids( - @Param("metricUuids") Collection<String> metricUuids); - - List<LiveMeasureDto> selectByComponentUuidsAndMetricKeys( - @Param("componentUuids") Collection<String> componentUuids, - @Param("metricKeys") Collection<String> metricKeys); - - List<LiveMeasureDto> selectByComponentUuidAndMetricKeys( - @Param("componentUuid") String componentUuid, - @Param("metricKeys") Collection<String> metricKeys); - - void scrollSelectByComponentUuidAndMetricKeys( - @Param("componentUuid") String componentUuid, - @Param("metricKeys") Collection<String> metricKeys, - ResultHandler<LiveMeasureDto> handler); - LiveMeasureDto selectByComponentUuidAndMetricKey( @Param("componentUuid") String componentUuid, @Param("metricKey") String metricKey); - void selectTreeByQuery( - @Param("query") MeasureTreeQuery measureQuery, - @Param("baseUuid") String baseUuid, - @Param("baseUuidPath") String baseUuidPath, - ResultHandler<LiveMeasureDto> resultHandler); - - @CheckForNull - Long findNclocOfBiggestBranchForProject(@Param("projectUuid") String projectUuid, @Param("ncloc") String nclocKey); - - List<LargestBranchNclocDto> getLargestBranchNclocPerProject(@Param("nclocUuid") String nclocUuid); - - List<ProjectLocDistributionDto> selectLargestBranchesLocDistribution(@Param("nclocUuid") String nclocUuid, @Param("nclocDistributionUuid") String nclocDistributionUuid); - - Long countProjectsHavingMeasure( - @Param("metric") String metric); - void insert( @Param("dto") LiveMeasureDto dto, @Param("uuid") String uuid, @@ -84,6 +52,4 @@ public interface LiveMeasureMapper { @Param("componentUuid") String componentUuid, @Param("excludedMetricUuids") List<String> excludedMetricUuids); - void deleteByComponent(@Param("componentUuid") String componentUuid); - } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDao.java index 1820903e7f9..326e7e5dc05 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDao.java @@ -24,10 +24,14 @@ import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.Set; +import org.apache.ibatis.session.ResultHandler; import org.sonar.api.utils.System2; import org.sonar.db.Dao; import org.sonar.db.DbSession; +import org.sonar.db.component.ComponentDto; +import static java.util.Collections.singletonList; +import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; import static org.sonar.db.DatabaseUtils.executeLargeInputs; public class MeasureDao implements Dao { @@ -55,7 +59,7 @@ public class MeasureDao implements Dao { */ public int insertOrUpdate(DbSession dbSession, MeasureDto dto) { long now = system2.now(); - Optional<MeasureDto> existingMeasureOpt = selectMeasure(dbSession, dto.getComponentUuid()); + Optional<MeasureDto> existingMeasureOpt = selectByComponentUuid(dbSession, dto.getComponentUuid()); if (existingMeasureOpt.isPresent()) { MeasureDto existingDto = existingMeasureOpt.get(); existingDto.getMetricValues().putAll(dto.getMetricValues()); @@ -68,8 +72,8 @@ public class MeasureDao implements Dao { } } - public Optional<MeasureDto> selectMeasure(DbSession dbSession, String componentUuid) { - List<MeasureDto> measures = mapper(dbSession).selectByComponentUuids(List.of(componentUuid)); + public Optional<MeasureDto> selectByComponentUuid(DbSession dbSession, String componentUuid) { + List<MeasureDto> measures = mapper(dbSession).selectByComponentUuids(singletonList(componentUuid)); if (!measures.isEmpty()) { // component_uuid column is unique. List can't have more than 1 item. return Optional.of(measures.get(0)); @@ -77,8 +81,8 @@ public class MeasureDao implements Dao { return Optional.empty(); } - public Optional<MeasureDto> selectMeasure(DbSession dbSession, String componentUuid, String metricKey) { - List<MeasureDto> measures = selectByComponentUuidsAndMetricKeys(dbSession, List.of(componentUuid), List.of(metricKey)); + public Optional<MeasureDto> selectByComponentUuidAndMetricKeys(DbSession dbSession, String componentUuid, Collection<String> metricKeys) { + List<MeasureDto> measures = selectByComponentUuidsAndMetricKeys(dbSession, singletonList(componentUuid), metricKeys); // component_uuid column is unique. List can't have more than 1 item. if (measures.size() == 1) { return Optional.of(measures.get(0)); @@ -86,7 +90,8 @@ public class MeasureDao implements Dao { return Optional.empty(); } - public List<MeasureDto> selectByComponentUuidsAndMetricKeys(DbSession dbSession, Collection<String> largeComponentUuids, Collection<String> metricKeys) { + public List<MeasureDto> selectByComponentUuidsAndMetricKeys(DbSession dbSession, Collection<String> largeComponentUuids, + Collection<String> metricKeys) { if (largeComponentUuids.isEmpty() || metricKeys.isEmpty()) { return Collections.emptyList(); } @@ -102,11 +107,50 @@ public class MeasureDao implements Dao { .toList(); } - public Set<MeasureHash> selectBranchMeasureHashes(DbSession dbSession, String branchUuid) { - return mapper(dbSession).selectBranchMeasureHashes(branchUuid); + public void scrollSelectByComponentUuid(DbSession dbSession, String componentUuid, ResultHandler<MeasureDto> handler) { + mapper(dbSession).scrollSelectByComponentUuid(componentUuid, handler); + } + + public Set<MeasureHash> selectMeasureHashesForBranch(DbSession dbSession, String branchUuid) { + return mapper(dbSession).selectMeasureHashesForBranch(branchUuid); + } + + public List<MeasureDto> selectBranchMeasuresForProject(DbSession dbSession, String projectUuid) { + return mapper(dbSession).selectBranchMeasuresForProject(projectUuid); + } + + public void selectTreeByQuery(DbSession dbSession, ComponentDto baseComponent, MeasureTreeQuery query, + ResultHandler<MeasureDto> resultHandler) { + if (query.returnsEmpty()) { + return; + } + mapper(dbSession).selectTreeByQuery(query, baseComponent.uuid(), query.getUuidPath(baseComponent), resultHandler); + } + + public List<ProjectMainBranchMeasureDto> selectAllForProjectMainBranches(DbSession dbSession) { + return mapper(dbSession).selectAllForProjectMainBranches(); + } + + public List<MeasureDto> selectAllForMainBranches(DbSession dbSession) { + return mapper(dbSession).selectAllForMainBranches(); + } + + public long findNclocOfBiggestBranchForProject(DbSession dbSession, String projectUuid) { + List<MeasureDto> branchMeasures = mapper(dbSession).selectBranchMeasuresForProject(projectUuid); + + long maxncloc = 0; + for (MeasureDto measure : branchMeasures) { + Long branchNcloc = measure.getLong(NCLOC_KEY); + if (branchNcloc != null && branchNcloc > maxncloc) { + maxncloc = branchNcloc; + } + } + + return maxncloc; } private static MeasureMapper mapper(DbSession dbSession) { return dbSession.getMapper(MeasureMapper.class); } + } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDto.java index e3abe752df3..7da512a97db 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDto.java @@ -99,6 +99,33 @@ public class MeasureDto { return String.valueOf(value); } + @CheckForNull + public Double getDouble(String metricKey) { + Object value = metricValues.get(metricKey); + if (value == null) { + return null; + } + return Double.parseDouble(value.toString()); + } + + @CheckForNull + public Integer getInt(String metricKey) { + Object value = metricValues.get(metricKey); + if (value == null) { + return null; + } + return (int) Double.parseDouble(value.toString()); + } + + @CheckForNull + public Long getLong(String metricKey) { + Object value = metricValues.get(metricKey); + if (value == null) { + return null; + } + return (long) Double.parseDouble(value.toString()); + } + @Override public String toString() { return "MeasureDto{" + diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureMapper.java index 69b4c2fefbe..a324666512b 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureMapper.java @@ -23,6 +23,7 @@ import java.util.Collection; import java.util.List; import java.util.Set; import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.session.ResultHandler; public interface MeasureMapper { @@ -36,5 +37,19 @@ public interface MeasureMapper { List<MeasureDto> selectByComponentUuids(@Param("componentUuids") Collection<String> componentUuids); - Set<MeasureHash> selectBranchMeasureHashes(@Param("branchUuid") String branchUuid); + void scrollSelectByComponentUuid(@Param("componentUuid") String componentUuid, ResultHandler<MeasureDto> handler); + + Set<MeasureHash> selectMeasureHashesForBranch(@Param("branchUuid") String branchUuid); + + List<MeasureDto> selectBranchMeasuresForProject(@Param("projectUuid") String projectUuid); + + void selectTreeByQuery( + @Param("query") MeasureTreeQuery measureQuery, + @Param("baseUuid") String baseUuid, + @Param("baseUuidPath") String baseUuidPath, + ResultHandler<MeasureDto> resultHandler); + + List<ProjectMainBranchMeasureDto> selectAllForProjectMainBranches(); + + List<MeasureDto> selectAllForMainBranches(); } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureTreeQuery.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureTreeQuery.java index 35f46dd6b75..61eb00b6de9 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureTreeQuery.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureTreeQuery.java @@ -44,14 +44,10 @@ public class MeasureTreeQuery { private final Collection<String> qualifiers; private final Strategy strategy; - @CheckForNull - private final Collection<String> metricUuids; - private MeasureTreeQuery(Builder builder) { this.nameOrKeyQuery = builder.nameOrKeyQuery; this.qualifiers = builder.qualifiers == null ? null : newArrayList(builder.qualifiers); this.strategy = requireNonNull(builder.strategy); - this.metricUuids = builder.metricUuids; } @CheckForNull @@ -76,11 +72,6 @@ public class MeasureTreeQuery { return strategy; } - @CheckForNull - public Collection<String> getMetricUuids() { - return metricUuids; - } - public String getUuidPath(ComponentDto component) { switch (strategy) { case CHILDREN: @@ -93,7 +84,7 @@ public class MeasureTreeQuery { } public boolean returnsEmpty() { - return (metricUuids != null && metricUuids.isEmpty()) || (qualifiers != null && qualifiers.isEmpty()); + return (qualifiers != null && qualifiers.isEmpty()); } public static Builder builder() { @@ -108,9 +99,6 @@ public class MeasureTreeQuery { private Collection<String> qualifiers; private Strategy strategy; - @CheckForNull - private Collection<String> metricUuids; - private Builder() { } @@ -129,14 +117,6 @@ public class MeasureTreeQuery { return this; } - /** - * All the measures are returned if parameter is {@code null}. - */ - public Builder setMetricUuids(@Nullable Collection<String> metricUuids) { - this.metricUuids = metricUuids; - return this; - } - public MeasureTreeQuery build() { return new MeasureTreeQuery(this); } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMainBranchMeasureDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMainBranchMeasureDto.java new file mode 100644 index 00000000000..22aa5db4d6d --- /dev/null +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMainBranchMeasureDto.java @@ -0,0 +1,51 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.db.measure; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import java.util.Map; +import java.util.TreeMap; + +public class ProjectMainBranchMeasureDto { + + private static final Gson GSON = new Gson(); + + private String projectUuid; + private Map<String, Object> metricValues = new TreeMap<>(); + + public ProjectMainBranchMeasureDto() { + // empty constructor + } + + public String getProjectUuid() { + return projectUuid; + } + + public Map<String, Object> getMetricValues() { + return metricValues; + } + + // used by MyBatis mapper + public void setJsonValue(String jsonValue) { + metricValues = GSON.fromJson(jsonValue, new TypeToken<TreeMap<String, Object>>() { + }.getType()); + } +} diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml index a921153abe6..bc684fd1e09 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml @@ -23,37 +23,6 @@ </foreach> </select> - <select id="selectForProjectMainBranchesByMetricUuids" parameterType="map" resultType="org.sonar.db.measure.ProjectMainBranchLiveMeasureDto"> - select p.uuid as projectUuid, lm.metric_uuid as metricUuid, lm.value as value, lm.text_value as textValue - from live_measures lm - inner join project_branches pb on pb.uuid = lm.component_uuid - inner join projects p on p.uuid = pb.project_uuid - where - lm.metric_uuid in <foreach item="metricUuid" collection="metricUuids" open="(" separator="," - close=")">#{metricUuid, jdbcType=VARCHAR}</foreach> - and p.qualifier = 'TRK' - and pb.is_main = ${_true} - </select> - - <select id="selectByComponentUuidsAndMetricKeys" parameterType="map" resultType="org.sonar.db.measure.LiveMeasureDto"> - select <include refid="columns"/> from live_measures lm - inner join metrics m on m.uuid = lm.metric_uuid - where - m.name in <foreach item="metricKey" collection="metricKeys" open="(" separator="," close=")">#{metricKey, jdbcType=VARCHAR}</foreach> - and lm.component_uuid in - <foreach item="componentUuid" collection="componentUuids" open="(" separator="," close=")"> - #{componentUuid, jdbcType=VARCHAR} - </foreach> - </select> - - <select id="selectByComponentUuidAndMetricKeys" parameterType="map" resultType="org.sonar.db.measure.LiveMeasureDto"> - select <include refid="columns"/> from live_measures lm - inner join metrics m on m.uuid = lm.metric_uuid - where - m.name in <foreach item="metricKey" collection="metricKeys" open="(" separator="," close=")">#{metricKey, jdbcType=VARCHAR}</foreach> - and lm.component_uuid = #{componentUuid, jdbcType=VARCHAR} - </select> - <select id="selectByComponentUuidAndMetricKey" parameterType="map" resultType="org.sonar.db.measure.LiveMeasureDto"> select <include refid="columns"/> from live_measures lm inner join metrics m on m.uuid = lm.metric_uuid @@ -62,71 +31,6 @@ and lm.component_uuid = #{componentUuid, jdbcType=VARCHAR} </select> - <select id="findNclocOfBiggestBranchForProject" parameterType="map" resultType="long"> - select max(lm.value) - from live_measures lm - inner join metrics m on m.uuid = lm.metric_uuid - inner join project_branches b on b.uuid = lm.component_uuid - inner join projects p on p.uuid = b.project_uuid and p.qualifier = 'TRK' - <where> - m.name = #{ncloc, jdbcType=VARCHAR} - and b.project_uuid = #{projectUuid,jdbcType=VARCHAR} - </where> - </select> - - <select id="getLargestBranchNclocPerProject" parameterType="map" resultType="LargestBranchNclocDto"> - select loc_grouped_branches.projectUuid, - loc_grouped_branches.projectName, - loc_grouped_branches.projectKey, - loc_grouped_branches.ncloc as loc, - loc_grouped_branches.branchName, - loc_grouped_branches.branchType - from ( - select pb.project_uuid as projectUuid, - p.name as projectName, - p.kee as projectKey, - pb.kee as branchName, - pb.branch_type as branchType, - lm.value as ncloc, - row_number() over (partition by pb.project_uuid order by lm.value desc, pb.is_main desc, pb.uuid asc) row_number - from live_measures lm - inner join project_branches pb on pb.uuid = lm.component_uuid - inner join projects p on p.uuid = pb.project_uuid - where lm.metric_uuid = #{nclocUuid, jdbcType=VARCHAR} - and p.qualifier ='TRK' - ) loc_grouped_branches - where loc_grouped_branches.row_number = 1 - order by ncloc desc - </select> - - <select id="selectLargestBranchesLocDistribution" parameterType="map" resultType="ProjectLocDistribution"> - select top_branches.project_uuid as projectUuid, - top_branches.uuid as branchUuid, - lm2.text_value as locDistribution from ( - SELECT loc_grouped_branches.uuid, loc_grouped_branches.project_uuid - FROM ( - SELECT b.uuid, b.project_uuid, ROW_NUMBER() OVER (PARTITION BY - b.project_uuid ORDER BY lm.value desc, b.is_main desc, b.uuid asc) row_number - from live_measures lm - inner join project_branches b on b.uuid = lm.component_uuid - inner join projects p on p.uuid = b.project_uuid - where lm.metric_uuid = #{nclocUuid, jdbcType=VARCHAR} - and p.qualifier ='TRK' - ) loc_grouped_branches - WHERE loc_grouped_branches.row_number = 1) top_branches - inner join live_measures lm2 on lm2.component_uuid = top_branches.uuid - where lm2.metric_uuid = #{nclocDistributionUuid, jdbcType=VARCHAR} - </select> - - <select id="countProjectsHavingMeasure" parameterType="map" resultType="long"> - select count(1) - from live_measures lm - inner join metrics m on m.uuid = lm.metric_uuid AND m.name = #{metric, jdbcType=VARCHAR} - inner join project_branches pb on pb.uuid = lm.project_uuid - inner join projects p on p.uuid = pb.project_uuid and p.qualifier = 'TRK' - - </select> - <insert id="insert" parameterType="map" useGeneratedKeys="false"> insert into live_measures ( uuid, @@ -162,12 +66,6 @@ and metric_uuid = #{dto.metricUuid, jdbcType=VARCHAR} </update> - <delete id="deleteByComponent" parameterType="map"> - delete from live_measures - where - component_uuid = #{componentUuid, jdbcType=VARCHAR} - </delete> - <update id="upsert" parameterType="map" useGeneratedKeys="false" databaseId="postgresql"> insert into live_measures ( uuid, @@ -214,67 +112,4 @@ </if> </sql> - <select id="scrollSelectByComponentUuidAndMetricKeys" resultType="org.sonar.db.measure.LiveMeasureDto" fetchSize="${_scrollFetchSize}" - resultSetType="FORWARD_ONLY"> - select <include refid="columns"/> from live_measures lm - inner join metrics m on m.uuid = lm.metric_uuid - where - m.name in <foreach item="metricKey" collection="metricKeys" open="(" separator="," close=")">#{metricKey, jdbcType=VARCHAR}</foreach> - and lm.component_uuid = #{componentUuid, jdbcType=VARCHAR} - </select> - - <select id="selectTreeByQuery" parameterType="map" resultType="org.sonar.db.measure.LiveMeasureDto" fetchSize="${_scrollFetchSize}" - resultSetType="FORWARD_ONLY"> - select <include refid="columns"/> from live_measures lm - inner join components p on p.uuid = lm.component_uuid - <!-- TODO do we really need another join on components ? Using lm.project_uuid should be enough --> - <include refid="org.sonar.db.component.ComponentMapper.selectDescendantsJoins"/> - <where> - <if test="query.getMetricUuids() != null"> - lm.metric_uuid in - <foreach item="metricUuid" collection="query.getMetricUuids()" open="(" separator="," - close=")">#{metricUuid,jdbcType=VARCHAR}</foreach> - </if> - and p.enabled = ${_true} - <if test="query.qualifiers != null"> - and p.qualifier in - <foreach collection="query.qualifiers" item="qualifier" open="(" close=")" separator=","> - #{qualifier,jdbcType=VARCHAR} - </foreach> - </if> - <if test="query.nameOrKeyQuery != null"> - and ( - p.kee = #{query.nameOrKeyQuery,jdbcType=VARCHAR} - or - upper(p.name) like #{query.nameOrKeyUpperLikeQuery,jdbcType=VARCHAR} escape '/' - ) - </if> - </where> - - -- Add measures of base component - union all - select <include refid="columns"/> from live_measures lm - inner join components p on p.uuid = lm.component_uuid and lm.component_uuid = #{baseUuid, jdbcType=VARCHAR} - <where> - <if test="query.getMetricUuids() != null"> - lm.metric_uuid in - <foreach item="metricUuid" collection="query.getMetricUuids()" open="(" separator="," - close=")">#{metricUuid,jdbcType=VARCHAR}</foreach> - </if> - and p.enabled = ${_true} - <if test="query.qualifiers != null"> - and p.qualifier in - <foreach collection="query.qualifiers" item="qualifier" open="(" close=")" separator=","> - #{qualifier,jdbcType=VARCHAR} - </foreach> - </if> - <if test="query.nameOrKeyQuery != null"> - and ( - p.kee = #{query.nameOrKeyQuery,jdbcType=VARCHAR} - or - upper(p.name) like #{query.nameOrKeyUpperLikeQuery,jdbcType=VARCHAR} escape '/' - ) - </if> - </where> - </select> </mapper> diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/MeasureMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/MeasureMapper.xml index 8fc634a5f1c..3bd68171aba 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/MeasureMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/MeasureMapper.xml @@ -47,10 +47,89 @@ </foreach> </select> - <select id="selectBranchMeasureHashes" resultType="org.sonar.db.measure.MeasureHash"> + <select id="scrollSelectByComponentUuid" resultType="org.sonar.db.measure.MeasureDto" fetchSize="${_scrollFetchSize}" + resultSetType="FORWARD_ONLY"> + select + <include refid="columns"/> + from measures m + where + m.component_uuid = #{componentUuid, jdbcType=VARCHAR} + </select> + + <select id="selectMeasureHashesForBranch" resultType="org.sonar.db.measure.MeasureHash"> select component_uuid, json_value_hash from measures where branch_uuid = #{branchUuid, jdbcType=VARCHAR} </select> + <select id="selectBranchMeasuresForProject" parameterType="map" resultType="org.sonar.db.measure.MeasureDto"> + select + <include refid="columns"/> + from measures m + inner join project_branches b on b.uuid = m.component_uuid + inner join projects p on p.uuid = b.project_uuid and p.qualifier = 'TRK' + where b.project_uuid = #{projectUuid,jdbcType=VARCHAR} + </select> + + <select id="selectTreeByQuery" parameterType="map" resultType="org.sonar.db.measure.MeasureDto" fetchSize="${_scrollFetchSize}" + resultSetType="FORWARD_ONLY"> + select <include refid="columns"/> from measures m + inner join components p on p.uuid = m.component_uuid + <!-- TODO do we really need another join on components ? Using m.project_uuid should be enough --> + <include refid="org.sonar.db.component.ComponentMapper.selectDescendantsJoins"/> + <where> + p.enabled = ${_true} + <if test="query.qualifiers != null"> + and p.qualifier in + <foreach collection="query.qualifiers" item="qualifier" open="(" close=")" separator=","> + #{qualifier,jdbcType=VARCHAR} + </foreach> + </if> + <if test="query.nameOrKeyQuery != null"> + and ( + p.kee = #{query.nameOrKeyQuery,jdbcType=VARCHAR} + or + upper(p.name) like #{query.nameOrKeyUpperLikeQuery,jdbcType=VARCHAR} escape '/' + ) + </if> + </where> + + -- Add measures of base component + union all + select <include refid="columns"/> from measures m + inner join components p on p.uuid = m.component_uuid and m.component_uuid = #{baseUuid, jdbcType=VARCHAR} + <where> + p.enabled = ${_true} + <if test="query.qualifiers != null"> + and p.qualifier in + <foreach collection="query.qualifiers" item="qualifier" open="(" close=")" separator=","> + #{qualifier,jdbcType=VARCHAR} + </foreach> + </if> + <if test="query.nameOrKeyQuery != null"> + and ( + p.kee = #{query.nameOrKeyQuery,jdbcType=VARCHAR} + or + upper(p.name) like #{query.nameOrKeyUpperLikeQuery,jdbcType=VARCHAR} escape '/' + ) + </if> + </where> + </select> + + <select id="selectAllForProjectMainBranches" resultType="org.sonar.db.measure.ProjectMainBranchMeasureDto"> + select p.uuid as projectUuid, m.json_value as jsonValue + from measures m + inner join project_branches pb on pb.uuid = m.component_uuid + inner join projects p on p.uuid = pb.project_uuid + where + p.qualifier = 'TRK' + and pb.is_main = ${_true} + </select> + + <select id="selectAllForMainBranches" resultType="org.sonar.db.measure.MeasureDto"> + select <include refid="columns"/> from measures m + inner join project_branches pb on pb.uuid = m.component_uuid and pb.is_main = ${_true} + inner join projects p on p.uuid = pb.project_uuid and p.qualifier = 'TRK' + </select> + </mapper> diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDaoTest.java index a0786410bba..da55449e229 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDaoTest.java @@ -19,15 +19,25 @@ */ package org.sonar.db.measure; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; +import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.math.RandomUtils; +import org.apache.ibatis.session.ResultHandler; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.resources.Qualifiers; import org.sonar.api.utils.System2; import org.sonar.db.DbSession; import org.sonar.db.DbTester; +import org.sonar.db.component.BranchDto; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.ProjectData; +import org.sonar.db.metric.MetricDto; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; @@ -37,6 +47,10 @@ import static org.assertj.core.api.Assertions.entry; import static org.assertj.core.groups.Tuple.tuple; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; +import static org.sonar.db.component.ComponentTesting.newDirectory; +import static org.sonar.db.component.ComponentTesting.newFileDto; +import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; import static org.sonar.db.measure.MeasureTesting.newMeasure; class MeasureDaoTest { @@ -110,7 +124,7 @@ class MeasureDaoTest { assertThat(count).isEqualTo(1); verifyTableSize(1); - assertThat(underTest.selectMeasure(db.getSession(), dto.getComponentUuid())) + assertThat(underTest.selectByComponentUuid(db.getSession(), dto.getComponentUuid())) .hasValueSatisfying(selected -> { assertThat(selected.getComponentUuid()).isEqualTo(dto.getComponentUuid()); assertThat(selected.getBranchUuid()).isEqualTo(dto.getBranchUuid()); @@ -123,30 +137,62 @@ class MeasureDaoTest { } @Test - void select_measure() { + void selectByComponentUuid() { MeasureDto measure1 = newMeasure(); MeasureDto measure2 = newMeasure(); underTest.insert(db.getSession(), measure1); underTest.insert(db.getSession(), measure2); - assertThat(underTest.selectMeasure(db.getSession(), measure1.getComponentUuid())) + assertThat(underTest.selectByComponentUuid(db.getSession(), measure1.getComponentUuid())) .hasValueSatisfying(selected -> assertThat(selected).usingRecursiveComparison().isEqualTo(measure1)); - assertThat(underTest.selectMeasure(db.getSession(), "unknown-component")).isEmpty(); + + assertThat(underTest.selectByComponentUuid(db.getSession(), "unknown-component")).isEmpty(); } @Test - void selectMeasure_with_single_metric() { - String metricKey = "metric1"; + void selectByComponentUuidAndMetricKeys() { + ComponentDto branch1 = db.components().insertPrivateProject().getMainBranchComponent(); + ComponentDto branch2 = db.components().insertPrivateProject().getMainBranchComponent(); + String metricKey1 = "metric1"; + String metricKey2 = "metric2"; + String metricKey3 = "metric3"; String value = "foo"; - MeasureDto measure1 = newMeasure().addValue(metricKey, value); - MeasureDto measure2 = newMeasure(); - underTest.insert(db.getSession(), measure1); - underTest.insert(db.getSession(), measure2); + db.measures().insertMeasure(branch1, m -> m.addValue(metricKey1, value).addValue(metricKey2, value).addValue(metricKey3, value)); + db.measures().insertMeasure(branch2, m -> m.addValue(metricKey1, value)); - assertThat(underTest.selectMeasure(db.getSession(), measure1.getComponentUuid(), metricKey)) - .hasValueSatisfying(selected -> assertThat(selected.getMetricValues()).containsOnly(entry(metricKey, value))); + assertThat(underTest.selectByComponentUuidAndMetricKeys(db.getSession(), branch1.uuid(), List.of(metricKey1, metricKey2))) + .hasValueSatisfying(selected -> { + assertThat(selected.getComponentUuid()).isEqualTo(branch1.uuid()); + assertThat(selected.getMetricValues()).containsOnlyKeys(metricKey1, metricKey2); + }); + + assertThat(underTest.selectByComponentUuidAndMetricKeys(db.getSession(), "unknown-component", List.of(metricKey1))).isEmpty(); + assertThat(underTest.selectByComponentUuidAndMetricKeys(db.getSession(), branch1.uuid(), List.of("random-metric"))).isEmpty(); + } - assertThat(underTest.selectMeasure(db.getSession(), "unknown-component", metricKey)).isEmpty(); + @Test + void selectByComponentUuidsAndMetricKeys() { + ComponentDto branch1 = db.components().insertPrivateProject().getMainBranchComponent(); + ComponentDto branch2 = db.components().insertPrivateProject().getMainBranchComponent(); + ComponentDto branch3 = db.components().insertPrivateProject().getMainBranchComponent(); + String metricKey1 = "metric1"; + String metricKey2 = "metric2"; + String metricKey3 = "metric3"; + String value = "foo"; + db.measures().insertMeasure(branch1, m -> m.addValue(metricKey1, value).addValue(metricKey2, value).addValue(metricKey3, value)); + db.measures().insertMeasure(branch2, m -> m.addValue(metricKey1, value)); + db.measures().insertMeasure(branch3, m -> m.addValue(metricKey1, value)); + + List<MeasureDto> measures = underTest.selectByComponentUuidsAndMetricKeys(db.getSession(), List.of(branch1.uuid(), branch2.uuid()), + List.of(metricKey1, metricKey2)); + assertThat(measures).hasSize(2); + assertThat(measures.stream().filter(m -> m.getComponentUuid().equals(branch1.uuid())).map(MeasureDto::getMetricValues).findFirst()) + .hasValueSatisfying(metricValues -> assertThat(metricValues).containsOnlyKeys(metricKey1, metricKey2)); + assertThat(measures.stream().filter(m -> m.getComponentUuid().equals(branch2.uuid())).map(MeasureDto::getMetricValues).findFirst()) + .hasValueSatisfying(metricValues -> assertThat(metricValues).containsOnlyKeys(metricKey1)); + + assertThat(underTest.selectByComponentUuidsAndMetricKeys(db.getSession(), List.of("unknown-component"), List.of(metricKey1))).isEmpty(); + assertThat(underTest.selectByComponentUuidsAndMetricKeys(db.getSession(), List.of(branch1.uuid()), List.of("random-metric"))).isEmpty(); } @Test @@ -255,7 +301,29 @@ class MeasureDaoTest { } @Test - void select_branch_measure_hashes() { + void scrollSelectByComponentUuid() { + List<MeasureDto> results = new ArrayList<>(); + MetricDto metric = db.measures().insertMetric(); + MetricDto metric2 = db.measures().insertMetric(); + ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); + ComponentDto project2 = db.components().insertPrivateProject().getMainBranchComponent(); + underTest.insertOrUpdate(db.getSession(), newMeasure(project, metric, 3.14)); + underTest.insertOrUpdate(db.getSession(), newMeasure(project, metric2, 4.54)); + underTest.insertOrUpdate(db.getSession(), newMeasure(project2, metric, 99.99)); + underTest.scrollSelectByComponentUuid(db.getSession(), project.uuid(), context -> results.add(context.getResultObject())); + + assertThat(results).hasSize(1); + assertThat(results).flatExtracting(m -> m.getMetricValues().entrySet().stream() + .map(entry -> tuple(m.getComponentUuid(), entry.getKey(), entry.getValue())) + .toList()) + .containsExactlyInAnyOrder( + tuple(project.uuid(), metric.getKey(), 3.14), + tuple(project.uuid(), metric2.getKey(), 4.54) + ); + } + + @Test + void select_measure_hashes_for_branch() { MeasureDto measure1 = new MeasureDto() .setComponentUuid("c1") .setBranchUuid("b1") @@ -276,16 +344,297 @@ class MeasureDaoTest { underTest.insert(db.getSession(), measure2); underTest.insert(db.getSession(), measure3); - assertThat(underTest.selectBranchMeasureHashes(db.getSession(), "b1")) + assertThat(underTest.selectMeasureHashesForBranch(db.getSession(), "b1")) .containsOnly(new MeasureHash("c1", hash1), new MeasureHash("c2", hash2)); } + @Test + void select_branch_measures_for_project() { + + // 2 branches on the same project, 1 branch on another project + ProjectData projectData = db.components().insertPrivateProject(); + BranchDto branch1 = projectData.getMainBranchDto(); + BranchDto branch2 = db.components().insertProjectBranch(projectData.getProjectDto()); + BranchDto branch3 = db.components().insertPrivateProject().getMainBranchDto(); + + // Insert measures for each branch and for a random component on branch1 + MetricDto metric = db.measures().insertMetric(); + MeasureDto measure1 = newMeasure(branch1, metric, 3); + MeasureDto measure2 = newMeasure(branch2, metric, 4); + MeasureDto measure3 = newMeasure(branch3, metric, 5); + MeasureDto measure4 = newMeasure(db.components().insertFile(branch1), metric, 6); + + underTest.insertOrUpdate(db.getSession(), measure1); + underTest.insertOrUpdate(db.getSession(), measure2); + underTest.insertOrUpdate(db.getSession(), measure3); + underTest.insertOrUpdate(db.getSession(), measure4); + + List<MeasureDto> measures = underTest.selectBranchMeasuresForProject(db.getSession(), projectData.projectUuid()); + assertThat(measures).hasSize(2); + assertThat(measures) + .flatExtracting(m -> m.getMetricValues().entrySet().stream() + .map(entry -> tuple(m.getComponentUuid(), m.getBranchUuid(), entry.getKey(), entry.getValue())) + .toList()) + .containsExactlyInAnyOrder( + tuple(branch1.getUuid(), branch1.getUuid(), metric.getKey(), 3.0), + tuple(branch2.getUuid(), branch2.getUuid(), metric.getKey(), 4.0) + ); + } + + @Test + void selectTreeByQuery_return_leaves_and_base_component() { + List<MeasureDto> results = new ArrayList<>(); + MetricDto metric1 = db.measures().insertMetric(); + MetricDto metric2 = db.measures().insertMetric(); + + ComponentDto branch1 = db.components().insertPrivateProject().getMainBranchComponent(); + MeasureDto measureOnProject1 = newMeasureForMetrics(branch1, metric1, metric2); + + ComponentDto file11 = db.components().insertComponent(newFileDto(branch1)); + ComponentDto file12 = db.components().insertComponent(newFileDto(branch1)); + MeasureDto measureOnFile11 = newMeasureForMetrics(file11, metric1, metric2); + MeasureDto measureOnFile12 = newMeasureForMetrics(file12, metric1, metric2); + + ComponentDto branch2 = db.components().insertPrivateProject().getMainBranchComponent(); + ComponentDto file21 = db.components().insertComponent(newFileDto(branch2)); + newMeasureForMetrics(file21, metric1, metric2); + + underTest.selectTreeByQuery(db.getSession(), branch1, + MeasureTreeQuery.builder() + .setStrategy(MeasureTreeQuery.Strategy.LEAVES).build(), + context -> results.add(context.getResultObject())); + + assertThat(results) + .hasSize(3) + .extracting(MeasureDto::getComponentUuid, measureDto -> measureDto.getMetricValues().get(metric1.getKey())) + .contains( + tuple(branch1.uuid(), measureOnProject1.getDouble(metric1.getKey())), + tuple(file11.uuid(), measureOnFile11.getDouble(metric1.getKey())), + tuple(file12.uuid(), measureOnFile12.getDouble(metric1.getKey())) + ); + } + + @Test + void selectTreeByQuery_return_children_and_several_measures() { + List<MeasureDto> results = new ArrayList<>(); + MetricDto metric1 = db.measures().insertMetric(); + MetricDto metric2 = db.measures().insertMetric(); + + ComponentDto branch = db.components().insertPrivateProject().getMainBranchComponent(); + + ComponentDto dir = db.components().insertComponent(newDirectory(branch, RandomStringUtils.randomAlphabetic(15))); + MeasureDto measureOnDirectory = newMeasureForMetrics(dir, metric1, metric2); + + ComponentDto file1 = db.components().insertComponent(newFileDto(dir)); + newMeasureForMetrics(file1, metric1, metric2); + + underTest.selectTreeByQuery(db.getSession(), branch, + MeasureTreeQuery.builder() + .setStrategy(MeasureTreeQuery.Strategy.CHILDREN).build(), + context -> results.add(context.getResultObject())); + + assertThat(results) + .hasSize(1) + .extracting(MeasureDto::getComponentUuid, measureDto -> measureDto.getMetricValues().get(metric1.getKey()), + measureDto -> measureDto.getMetricValues().get(metric2.getKey())) + .contains(tuple(dir.uuid(), measureOnDirectory.getDouble(metric1.getKey()), measureOnDirectory.getDouble(metric2.getKey()))); + } + + @Test + void selectTreeByQuery_return_leaves_filtered_by_qualifier() { + List<MeasureDto> results = new ArrayList<>(); + MetricDto metric1 = db.measures().insertMetric(); + MetricDto metric2 = db.measures().insertMetric(); + + ComponentDto branch1 = db.components().insertPrivateProject().getMainBranchComponent(); + newMeasureForMetrics(branch1, metric1, metric2); + + ComponentDto file = db.components().insertComponent(newFileDto(branch1)); + ComponentDto uts = db.components().insertComponent(newFileDto(branch1).setQualifier(Qualifiers.UNIT_TEST_FILE)); + MeasureDto measureOnFile11 = newMeasureForMetrics(file, metric1, metric2); + newMeasureForMetrics(uts, metric1, metric2); + + underTest.selectTreeByQuery(db.getSession(), branch1, + MeasureTreeQuery.builder() + .setQualifiers(Collections.singletonList(Qualifiers.FILE)) + .setStrategy(MeasureTreeQuery.Strategy.LEAVES).build(), + context -> results.add(context.getResultObject())); + + assertThat(results) + .hasSize(1) + .extracting(MeasureDto::getComponentUuid, measureDto -> measureDto.getMetricValues().get(metric1.getKey())) + .contains( + tuple(file.uuid(), measureOnFile11.getDouble(metric1.getKey())) + ); + } + + @Test + void selectTreeByQuery_return_leaves_filtered_by_name_or_key() { + List<MeasureDto> results = new ArrayList<>(); + MetricDto metric1 = db.measures().insertMetric(); + MetricDto metric2 = db.measures().insertMetric(); + + ComponentDto matchingBranch = + db.components().insertPrivateProject(project -> project.setName("matchingBranch")).getMainBranchComponent(); + MeasureDto measureOnProject = newMeasureForMetrics(matchingBranch, metric1, metric2); + + ComponentDto fileWithMatchingName = db.components().insertComponent(newFileDto(matchingBranch).setName("matchingName")); + ComponentDto fileWithMatchingKey = db.components().insertComponent(newFileDto(matchingBranch).setName("anotherName").setKey("matching" + )); + ComponentDto fileNotMatching = db.components().insertComponent(newFileDto(matchingBranch).setName("anotherName").setKey("anotherKee")); + + MeasureDto measureOnMatchingName = newMeasureForMetrics(fileWithMatchingName, metric1, metric2); + MeasureDto measureOnMatchingKee = newMeasureForMetrics(fileWithMatchingKey, metric1, metric2); + newMeasureForMetrics(fileNotMatching, metric1, metric2); + + underTest.selectTreeByQuery(db.getSession(), matchingBranch, + MeasureTreeQuery.builder() + .setNameOrKeyQuery("matching") + .setStrategy(MeasureTreeQuery.Strategy.LEAVES).build(), + context -> results.add(context.getResultObject())); + + assertThat(results) + .hasSize(3) + .extracting(MeasureDto::getComponentUuid, measureDto -> measureDto.getMetricValues().get(metric1.getKey())) + .contains( + tuple(matchingBranch.uuid(), measureOnProject.getDouble(metric1.getKey())), + tuple(fileWithMatchingName.uuid(), measureOnMatchingName.getDouble(metric1.getKey())), + tuple(fileWithMatchingKey.uuid(), measureOnMatchingKee.getDouble(metric1.getKey())) + ); + } + + @Test + void selectTreeByQuery_with_empty_results() { + List<MeasureDto> results = new ArrayList<>(); + underTest.selectTreeByQuery(db.getSession(), newPrivateProjectDto(), + MeasureTreeQuery.builder().setStrategy(MeasureTreeQuery.Strategy.LEAVES).build(), + context -> results.add(context.getResultObject())); + + assertThat(results).isEmpty(); + } + + @Test + void selectTreeByQuery_does_not_use_db_when_query_returns_empty() { + DbSession dbSession = mock(DbSession.class); + MeasureTreeQuery query = mock(MeasureTreeQuery.class); + when(query.returnsEmpty()).thenReturn(true); + + List<MeasureDto> results = new ArrayList<>(); + ResultHandler<MeasureDto> resultHandler = context -> results.add(context.getResultObject()); + underTest.selectTreeByQuery(dbSession, new ComponentDto(), query, resultHandler); + + assertThat(results).isEmpty(); + verifyNoInteractions(dbSession); + } + + @Test + void selectAllForProjectMainBranches() { + ProjectData projectData1 = db.components().insertPrivateProject(); + BranchDto branch1 = projectData1.getMainBranchDto(); + BranchDto branch2 = db.components().insertProjectBranch(projectData1.getProjectDto()); + + ProjectData projectData2 = db.components().insertPrivateProject(); + BranchDto branch3 = projectData2.getMainBranchDto(); + BranchDto branch4 = db.components().insertProjectBranch(projectData2.getProjectDto()); + + // Insert measures for each branch and for a random component on branch1 + MetricDto metric = db.measures().insertMetric(); + MeasureDto measure1 = newMeasure(branch1, metric, 3); + MeasureDto measure2 = newMeasure(branch2, metric, 4); + MeasureDto measure3 = newMeasure(branch3, metric, 5); + MeasureDto measure4 = newMeasure(branch4, metric, 6); + MeasureDto measure5 = newMeasure(db.components().insertFile(branch1), metric, 7); + + underTest.insertOrUpdate(db.getSession(), measure1); + underTest.insertOrUpdate(db.getSession(), measure2); + underTest.insertOrUpdate(db.getSession(), measure3); + underTest.insertOrUpdate(db.getSession(), measure4); + underTest.insertOrUpdate(db.getSession(), measure5); + + List<ProjectMainBranchMeasureDto> measures = underTest.selectAllForProjectMainBranches(db.getSession()); + assertThat(measures).hasSize(2); + assertThat(measures) + .flatExtracting(m -> m.getMetricValues().entrySet().stream() + .map(entry -> tuple(m.getProjectUuid(), entry.getKey(), entry.getValue())) + .toList()) + .containsExactlyInAnyOrder( + tuple(projectData1.projectUuid(), metric.getKey(), 3.0), + tuple(projectData2.projectUuid(), metric.getKey(), 5.0) + ); + } + + @Test + void selectAllForMainBranches() { + ProjectData projectData1 = db.components().insertPrivateProject(); + BranchDto branch1 = projectData1.getMainBranchDto(); + BranchDto branch2 = db.components().insertProjectBranch(projectData1.getProjectDto()); + + ProjectData projectData2 = db.components().insertPrivateProject(); + BranchDto branch3 = projectData2.getMainBranchDto(); + BranchDto branch4 = db.components().insertProjectBranch(projectData2.getProjectDto()); + + // Insert measures for each branch and for a random component on branch1 + MetricDto metric = db.measures().insertMetric(); + MeasureDto measure1 = newMeasure(branch1, metric, 3); + MeasureDto measure2 = newMeasure(branch2, metric, 4); + MeasureDto measure3 = newMeasure(branch3, metric, 5); + MeasureDto measure4 = newMeasure(branch4, metric, 6); + MeasureDto measure5 = newMeasure(db.components().insertFile(branch1), metric, 7); + + underTest.insertOrUpdate(db.getSession(), measure1); + underTest.insertOrUpdate(db.getSession(), measure2); + underTest.insertOrUpdate(db.getSession(), measure3); + underTest.insertOrUpdate(db.getSession(), measure4); + underTest.insertOrUpdate(db.getSession(), measure5); + + List<MeasureDto> measures = underTest.selectAllForMainBranches(db.getSession()); + assertThat(measures).hasSize(2); + assertThat(measures) + .flatExtracting(m -> m.getMetricValues().entrySet().stream() + .map(entry -> tuple(m.getComponentUuid(), m.getBranchUuid(), entry.getKey(), entry.getValue())) + .toList()) + .containsExactlyInAnyOrder( + tuple(branch1.getUuid(), branch1.getUuid(), metric.getKey(), 3.0), + tuple(branch3.getUuid(), branch3.getUuid(), metric.getKey(), 5.0) + ); + } + + @Test + void findNclocOfBiggestBranchForProject() { + // 2 branches on the same project, 1 branch on 2 other projects + ProjectData projectData = db.components().insertPrivateProject(); + BranchDto branch1 = projectData.getMainBranchDto(); + BranchDto branch2 = db.components().insertProjectBranch(projectData.getProjectDto()); + BranchDto branch3 = db.components().insertPrivateProject().getMainBranchDto(); + ProjectData project2 = db.components().insertPrivateProject(); + + // Insert measures for each branch and for a random component on branch1 + MetricDto metric = db.measures().insertMetric(metricDto -> metricDto.setKey(CoreMetrics.NCLOC_KEY)); + MeasureDto measure1 = newMeasure(branch1, metric, 3); + MeasureDto measure2 = newMeasure(branch2, metric, 4); + MeasureDto measure3 = newMeasure(branch3, metric, 5); + MeasureDto measure4 = newMeasure(db.components().insertFile(branch1), metric, 6); + + underTest.insertOrUpdate(db.getSession(), measure1); + underTest.insertOrUpdate(db.getSession(), measure2); + underTest.insertOrUpdate(db.getSession(), measure3); + underTest.insertOrUpdate(db.getSession(), measure4); + + assertThat(underTest.findNclocOfBiggestBranchForProject(db.getSession(), projectData.projectUuid())).isEqualTo(4); + assertThat(underTest.findNclocOfBiggestBranchForProject(db.getSession(), project2.projectUuid())).isZero(); + } + + private MeasureDto newMeasureForMetrics(ComponentDto componentDto, MetricDto... metrics) { + return db.measures().insertMeasure(componentDto, + m -> Arrays.stream(metrics).forEach(metric -> m.addValue(metric.getKey(), RandomUtils.nextInt(50)))); + } + private void verifyTableSize(int expectedSize) { assertThat(db.countRowsOfTable(db.getSession(), "measures")).isEqualTo(expectedSize); } private void verifyPersisted(MeasureDto dto) { - assertThat(underTest.selectMeasure(db.getSession(), dto.getComponentUuid())).hasValueSatisfying(selected -> { + assertThat(underTest.selectByComponentUuid(db.getSession(), dto.getComponentUuid())).hasValueSatisfying(selected -> { assertThat(selected).usingRecursiveComparison().isEqualTo(dto); }); } diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDtoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDtoTest.java index 7a582fc1320..81d07a8ec60 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDtoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDtoTest.java @@ -22,6 +22,8 @@ package org.sonar.db.measure; import java.util.List; import java.util.Map; import java.util.TreeMap; +import java.util.function.BiFunction; +import org.apache.commons.lang.math.RandomUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -31,6 +33,30 @@ import static org.assertj.core.api.Assertions.assertThat; class MeasureDtoTest { + @Test + void getDouble_returns_double_value() { + String metricKey = randomAlphabetic(7); + double value = RandomUtils.nextDouble(); + MeasureDto measureDto = new MeasureDto().addValue(metricKey, value); + assertThat(measureDto.getDouble(metricKey)).isEqualTo(value); + } + + @Test + void getInt_returns_int_value() { + String metricKey = randomAlphabetic(7); + int value = RandomUtils.nextInt(); + MeasureDto measureDto = new MeasureDto().addValue(metricKey, value); + assertThat(measureDto.getInt(metricKey)).isEqualTo(value); + } + + @Test + void getLong_returns_long_value() { + String metricKey = randomAlphabetic(7); + long value = RandomUtils.nextInt(); + MeasureDto measureDto = new MeasureDto().addValue(metricKey, value); + assertThat(measureDto.getLong(metricKey)).isEqualTo(value); + } + @ParameterizedTest @MethodSource("valuesOfDifferentTypes") void getString_returns_string_value(Object value) { @@ -43,11 +69,21 @@ class MeasureDtoTest { return List.of(2, 3.14, "foo"); } - @Test - void getString_returns_null_for_nonexistent_metric() { + @ParameterizedTest + @MethodSource("gettersOfDifferentTypes") + void getters_return_null_for_nonexistent_metric(BiFunction<MeasureDto, String, Object> getter) { String metricKey = randomAlphabetic(7); MeasureDto measureDto = new MeasureDto(); - assertThat(measureDto.getString(metricKey)).isNull(); + assertThat(getter.apply(measureDto, metricKey)).isNull(); + } + + public static List<BiFunction<MeasureDto, String, Object>> gettersOfDifferentTypes() { + return List.of( + MeasureDto::getInt, + MeasureDto::getLong, + MeasureDto::getDouble, + MeasureDto::getString + ); } @Test diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureTreeQueryTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureTreeQueryTest.java index c1678135e3a..033f8971191 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureTreeQueryTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureTreeQueryTest.java @@ -37,13 +37,11 @@ class MeasureTreeQueryTest { .setStrategy(CHILDREN) .setQualifiers(asList("FIL", "DIR")) .setNameOrKeyQuery("teSt") - .setMetricUuids(asList("10", "11")) .build(); assertThat(query.getStrategy()).isEqualTo(CHILDREN); assertThat(query.getQualifiers()).containsOnly("FIL", "DIR"); assertThat(query.getNameOrKeyQuery()).isEqualTo("teSt"); - assertThat(query.getMetricUuids()).containsOnly("10", "11"); } @Test @@ -55,7 +53,6 @@ class MeasureTreeQueryTest { assertThat(query.getStrategy()).isEqualTo(CHILDREN); assertThat(query.getQualifiers()).isNull(); assertThat(query.getNameOrKeyQuery()).isNull(); - assertThat(query.getMetricUuids()).isNull(); } @Test @@ -80,19 +77,6 @@ class MeasureTreeQueryTest { } @Test - void return_empty_when_metrics_is_empty() { - assertThat(MeasureTreeQuery.builder() - .setStrategy(CHILDREN) - .setMetricUuids(Collections.emptyList()) - .build().returnsEmpty()).isTrue(); - - assertThat(MeasureTreeQuery.builder() - .setStrategy(CHILDREN) - .setMetricUuids(null) - .build().returnsEmpty()).isFalse(); - } - - @Test void return_empty_when_qualifiers_is_empty() { assertThat(MeasureTreeQuery.builder() .setStrategy(CHILDREN) diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureDbTester.java index f834b2de6f7..3d4f43d5fa4 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureDbTester.java @@ -109,9 +109,24 @@ public class MeasureDbTester { @SafeVarargs public final MeasureDto insertMeasure(ComponentDto component, Consumer<MeasureDto>... consumers) { + return insertMeasure(component.uuid(), component.branchUuid(), consumers); + } + + @SafeVarargs + public final MeasureDto insertMeasure(BranchDto branch, Consumer<MeasureDto>... consumers) { + return insertMeasure(branch.getUuid(), branch.getUuid(), consumers); + } + + @SafeVarargs + public final MeasureDto insertMeasure(ProjectData projectData, Consumer<MeasureDto>... consumers) { + ComponentDto component = projectData.getMainBranchComponent(); + return insertMeasure(component.uuid(), component.branchUuid(), consumers); + } + + private MeasureDto insertMeasure(String componentUuid, String branchUuid, Consumer<MeasureDto>... consumers) { MeasureDto dto = new MeasureDto() - .setComponentUuid(component.uuid()) - .setBranchUuid(component.branchUuid()); + .setComponentUuid(componentUuid) + .setBranchUuid(branchUuid); Arrays.stream(consumers).forEach(c -> c.accept(dto)); dbClient.measureDao().insertOrUpdate(db.getSession(), dto); db.getSession().commit(); diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureTesting.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureTesting.java index 89db3b7adc5..4982aacdefc 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureTesting.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureTesting.java @@ -92,19 +92,22 @@ public class MeasureTesting { } public static MeasureDto newMeasure() { - MeasureDto measureDto = new MeasureDto() - .setComponentUuid(String.valueOf(cursor++)) - .setBranchUuid(String.valueOf(cursor++)) - .addValue("metric" + cursor++, (double) cursor++); - measureDto.computeJsonValueHash(); - return measureDto; + return newMeasure(String.valueOf(cursor++), String.valueOf(cursor++), "metric" + cursor++, (double) cursor++); } public static MeasureDto newMeasure(ComponentDto component, MetricDto metric, Object value) { + return newMeasure(component.uuid(), component.branchUuid(), metric.getKey(), value); + } + + public static MeasureDto newMeasure(BranchDto branch, MetricDto metric, Object value) { + return newMeasure(branch.getUuid(), branch.getUuid(), metric.getKey(), value); + } + + private static MeasureDto newMeasure(String componentUuid, String branchUuid, String metricKey, Object value) { MeasureDto measureDto = new MeasureDto() - .setComponentUuid(component.uuid()) - .setBranchUuid(component.branchUuid()) - .addValue(metric.getKey(), value); + .setComponentUuid(componentUuid) + .setBranchUuid(branchUuid) + .addValue(metricKey, value); measureDto.computeJsonValueHash(); return measureDto; } diff --git a/server/sonar-telemetry/src/it/java/org/sonar/telemetry/legacy/TelemetryDataLoaderImplIT.java b/server/sonar-telemetry/src/it/java/org/sonar/telemetry/legacy/TelemetryDataLoaderImplIT.java index 42af73dcce8..a523f348f1e 100644 --- a/server/sonar-telemetry/src/it/java/org/sonar/telemetry/legacy/TelemetryDataLoaderImplIT.java +++ b/server/sonar-telemetry/src/it/java/org/sonar/telemetry/legacy/TelemetryDataLoaderImplIT.java @@ -123,15 +123,18 @@ class TelemetryDataLoaderImplIT { private final QualityGateFinder qualityGateFinder = new QualityGateFinder(db.getDbClient()); private final QualityProfileDataProvider qualityProfileDataProvider = new QualityProfileDataProvider(db.getDbClient(), new QProfileComparison(db.getDbClient())); + private final ProjectLocDistributionDataProvider projectLocDistributionDataProvider = new ProjectLocDistributionDataProvider(db.getDbClient()); private final InternalProperties internalProperties = spy(new MapInternalProperties()); private final ManagedInstanceService managedInstanceService = mock(ManagedInstanceService.class); private final CloudUsageDataProvider cloudUsageDataProvider = mock(CloudUsageDataProvider.class); private final AiCodeAssuranceVerifier aiCodeAssuranceVerifier = mock(AiCodeAssuranceVerifier.class); private final TelemetryDataLoader communityUnderTest = new TelemetryDataLoaderImpl(server, db.getDbClient(), pluginRepository, editionProvider, - internalProperties, configuration, containerSupport, qualityGateCaycChecker, qualityGateFinder, managedInstanceService, cloudUsageDataProvider, qualityProfileDataProvider, aiCodeAssuranceVerifier); + internalProperties, configuration, containerSupport, qualityGateCaycChecker, qualityGateFinder, managedInstanceService, cloudUsageDataProvider, qualityProfileDataProvider, aiCodeAssuranceVerifier, + projectLocDistributionDataProvider); private final TelemetryDataLoader commercialUnderTest = new TelemetryDataLoaderImpl(server, db.getDbClient(), pluginRepository, editionProvider, - internalProperties, configuration, containerSupport, qualityGateCaycChecker, qualityGateFinder, managedInstanceService, cloudUsageDataProvider, qualityProfileDataProvider, aiCodeAssuranceVerifier); + internalProperties, configuration, containerSupport, qualityGateCaycChecker, qualityGateFinder, managedInstanceService, cloudUsageDataProvider, qualityProfileDataProvider, aiCodeAssuranceVerifier, + projectLocDistributionDataProvider); private QualityGateDto builtInDefaultQualityGate; private MetricDto bugsDto; @@ -184,27 +187,27 @@ class TelemetryDataLoaderImplIT { ComponentDto mainBranch1 = projectData1.getMainBranchComponent(); var branch1 = db.components().insertProjectBranch(mainBranch1, branchDto -> branchDto.setKey("reference")); var branch2 = db.components().insertProjectBranch(mainBranch1, branchDto -> branchDto.setKey("custom")); - db.measures().insertLiveMeasure(mainBranch1, lines, m -> m.setValue(110d)); - db.measures().insertLiveMeasure(mainBranch1, ncloc, m -> m.setValue(110d)); - db.measures().insertLiveMeasure(mainBranch1, coverage, m -> m.setValue(80d)); - db.measures().insertLiveMeasure(mainBranch1, nclocDistrib, m -> m.setValue(null).setData("java=70;js=30;kotlin=10")); - db.measures().insertLiveMeasure(mainBranch1, bugsDto, m -> m.setValue(1d)); - db.measures().insertLiveMeasure(mainBranch1, vulnerabilitiesDto, m -> m.setValue(1d).setData((String) null)); - db.measures().insertLiveMeasure(mainBranch1, securityHotspotsDto, m -> m.setValue(1d).setData((String) null)); - db.measures().insertLiveMeasure(mainBranch1, developmentCostDto, m -> m.setData("50").setValue(null)); - db.measures().insertLiveMeasure(mainBranch1, technicalDebtDto, m -> m.setValue(5d).setData((String) null)); + db.measures().insertMeasure(mainBranch1, m -> m.addValue(lines.getKey(), 110d)); + db.measures().insertMeasure(mainBranch1, m -> m.addValue(ncloc.getKey(), 110d)); + db.measures().insertMeasure(mainBranch1, m -> m.addValue(coverage.getKey(), 80d)); + db.measures().insertMeasure(mainBranch1, m -> m.addValue(nclocDistrib.getKey(), "java=70;js=30;kotlin=10")); + db.measures().insertMeasure(mainBranch1, m -> m.addValue(bugsDto.getKey(), 1d)); + db.measures().insertMeasure(mainBranch1, m -> m.addValue(vulnerabilitiesDto.getKey(), 1d)); + db.measures().insertMeasure(mainBranch1, m -> m.addValue(securityHotspotsDto.getKey(), 1d)); + db.measures().insertMeasure(mainBranch1, m -> m.addValue(developmentCostDto.getKey(), "50")); + db.measures().insertMeasure(mainBranch1, m -> m.addValue(technicalDebtDto.getKey(), 5d)); // Measures on other branches - db.measures().insertLiveMeasure(branch1, technicalDebtDto, m -> m.setValue(6d).setData((String) null)); - db.measures().insertLiveMeasure(branch2, technicalDebtDto, m -> m.setValue(7d).setData((String) null)); + db.measures().insertMeasure(branch1, m -> m.addValue(technicalDebtDto.getKey(), 6d)); + db.measures().insertMeasure(branch2, m -> m.addValue(technicalDebtDto.getKey(), 7d)); ProjectData projectData2 = db.components().insertPrivateProject(ComponentDbTester.defaults(), projectDto -> projectDto.setAiCodeAssurance(false)); when(aiCodeAssuranceVerifier.isAiCodeAssured(projectData2.getProjectDto().getAiCodeAssurance())).thenReturn(false); ComponentDto mainBranch2 = projectData2.getMainBranchComponent(); - db.measures().insertLiveMeasure(mainBranch2, lines, m -> m.setValue(200d)); - db.measures().insertLiveMeasure(mainBranch2, ncloc, m -> m.setValue(200d)); - db.measures().insertLiveMeasure(mainBranch2, coverage, m -> m.setValue(80d)); - db.measures().insertLiveMeasure(mainBranch2, nclocDistrib, m -> m.setValue(null).setData("java=180;js=20")); + db.measures().insertMeasure(mainBranch2, m -> m.addValue(lines.getKey(), 200d)); + db.measures().insertMeasure(mainBranch2, m -> m.addValue(ncloc.getKey(), 200d)); + db.measures().insertMeasure(mainBranch2, m -> m.addValue(coverage.getKey(), 80d)); + db.measures().insertMeasure(mainBranch2, m -> m.addValue(nclocDistrib.getKey(), "java=180;js=20")); SnapshotDto project1Analysis = db.components().insertSnapshot(mainBranch1, t -> t.setLast(true).setAnalysisDate(analysisDate)); SnapshotDto project2Analysis = db.components().insertSnapshot(mainBranch2, t -> t.setLast(true).setAnalysisDate(analysisDate)); @@ -417,16 +420,16 @@ class TelemetryDataLoaderImplIT { db.qualityProfiles().associateWithProject(projectData.getProjectDto(), javaQP, kotlinQP, jsQP); ComponentDto mainBranch = projectData.getMainBranchComponent(); - db.measures().insertLiveMeasure(mainBranch, lines, m -> m.setValue(110d)); - db.measures().insertLiveMeasure(mainBranch, ncloc, m -> m.setValue(110d)); - db.measures().insertLiveMeasure(mainBranch, coverage, m -> m.setValue(80d)); - db.measures().insertLiveMeasure(mainBranch, nclocDistrib, m -> m.setValue(null).setData("java=70;js=30;kotlin=10")); + db.measures().insertMeasure(mainBranch, m -> m.addValue(lines.getKey(), 110d)); + db.measures().insertMeasure(mainBranch, m -> m.addValue(ncloc.getKey(), 110d)); + db.measures().insertMeasure(mainBranch, m -> m.addValue(coverage.getKey(), 80d)); + db.measures().insertMeasure(mainBranch, m -> m.addValue(nclocDistrib.getKey(), "java=70;js=30;kotlin=10")); ComponentDto branch = db.components().insertProjectBranch(mainBranch, b -> b.setBranchType(BRANCH)); - db.measures().insertLiveMeasure(branch, lines, m -> m.setValue(180d)); - db.measures().insertLiveMeasure(branch, ncloc, m -> m.setValue(180d)); - db.measures().insertLiveMeasure(branch, coverage, m -> m.setValue(80d)); - db.measures().insertLiveMeasure(branch, nclocDistrib, m -> m.setValue(null).setData("java=100;js=50;kotlin=30")); + db.measures().insertMeasure(branch, m -> m.addValue(lines.getKey(), 180d)); + db.measures().insertMeasure(branch, m -> m.addValue(ncloc.getKey(), 180d)); + db.measures().insertMeasure(branch, m -> m.addValue(coverage.getKey(), 80d)); + db.measures().insertMeasure(branch, m -> m.addValue(nclocDistrib.getKey(), "java=100;js=50;kotlin=30")); SnapshotDto project1Analysis = db.components().insertSnapshot(mainBranch, t -> t.setLast(true)); SnapshotDto project2Analysis = db.components().insertSnapshot(branch, t -> t.setLast(true)); @@ -464,12 +467,12 @@ class TelemetryDataLoaderImplIT { db.qualityProfiles().associateWithProject(projectData.getProjectDto(), jsQP); ComponentDto mainBranch = projectData.getMainBranchComponent(); - db.measures().insertLiveMeasure(mainBranch, ncloc, m -> m.setValue(110d)); - db.measures().insertLiveMeasure(mainBranch, nclocDistrib, m -> m.setValue(null).setData("java=70;js=30;kotlin=10")); + db.measures().insertMeasure(mainBranch, m -> m.addValue(ncloc.getKey(), 110d)); + db.measures().insertMeasure(mainBranch, m -> m.addValue(nclocDistrib.getKey(), "java=70;js=30;kotlin=10")); ComponentDto branch = db.components().insertProjectBranch(mainBranch, b -> b.setBranchType(BRANCH)); - db.measures().insertLiveMeasure(branch, ncloc, m -> m.setValue(180d)); - db.measures().insertLiveMeasure(branch, nclocDistrib, m -> m.setValue(null).setData("java=100;js=50;kotlin=30")); + db.measures().insertMeasure(branch, m -> m.addValue(ncloc.getKey(), 180d)); + db.measures().insertMeasure(branch, m -> m.addValue(nclocDistrib.getKey(), "java=100;js=50;kotlin=30")); SnapshotDto project1Analysis = db.components().insertSnapshot(mainBranch, t -> t.setLast(true)); SnapshotDto project2Analysis = db.components().insertSnapshot(branch, t -> t.setLast(true)); @@ -614,9 +617,9 @@ class TelemetryDataLoaderImplIT { MetricDto unanalyzedCpp = db.measures().insertMetric(m -> m.setKey(UNANALYZED_CPP_KEY)); ComponentDto project1 = db.components().insertPublicProject().getMainBranchComponent(); ComponentDto project2 = db.components().insertPublicProject().getMainBranchComponent(); - db.measures().insertLiveMeasure(project1, unanalyzedC); - db.measures().insertLiveMeasure(project2, unanalyzedC); - db.measures().insertLiveMeasure(project2, unanalyzedCpp); + db.measures().insertMeasure(project1, m -> m.addValue(unanalyzedC.getKey(), 1)); + db.measures().insertMeasure(project2, m -> m.addValue(unanalyzedC.getKey(), 1)); + db.measures().insertMeasure(project2, m -> m.addValue(unanalyzedCpp.getKey(), 1)); TelemetryData data = communityUnderTest.load(); @@ -631,8 +634,8 @@ class TelemetryDataLoaderImplIT { MetricDto unanalyzedCpp = db.measures().insertMetric(m -> m.setKey(UNANALYZED_CPP_KEY)); ComponentDto project1 = db.components().insertPublicProject().getMainBranchComponent(); ComponentDto project2 = db.components().insertPublicProject().getMainBranchComponent(); - db.measures().insertLiveMeasure(project1, unanalyzedC); - db.measures().insertLiveMeasure(project2, unanalyzedCpp); + db.measures().insertMeasure(project1, m -> m.addValue(unanalyzedC.getKey(), 1)); + db.measures().insertMeasure(project2, m -> m.addValue(unanalyzedCpp.getKey(), 1)); TelemetryData data = communityUnderTest.load(); diff --git a/server/sonar-telemetry/src/main/java/org/sonar/telemetry/legacy/ProjectLocDistributionDataProvider.java b/server/sonar-telemetry/src/main/java/org/sonar/telemetry/legacy/ProjectLocDistributionDataProvider.java new file mode 100644 index 00000000000..03e01d9a951 --- /dev/null +++ b/server/sonar-telemetry/src/main/java/org/sonar/telemetry/legacy/ProjectLocDistributionDataProvider.java @@ -0,0 +1,68 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.telemetry.legacy; + +import java.util.ArrayList; +import java.util.List; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.measure.MeasureDto; +import org.sonar.db.measure.ProjectLocDistributionDto; +import org.sonar.db.project.ProjectDto; + +import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; +import static org.sonar.api.measures.CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY; + +public class ProjectLocDistributionDataProvider { + + private final DbClient dbClient; + + public ProjectLocDistributionDataProvider(DbClient dbClient) { + this.dbClient = dbClient; + } + + /** + * Returns the loc distribution of the largest branch of each project. + */ + public List<ProjectLocDistributionDto> getProjectLocDistribution(DbSession dbSession) { + List<ProjectLocDistributionDto> branchesWithLargestNcloc = new ArrayList<>(); + List<ProjectDto> projects = dbClient.projectDao().selectProjects(dbSession); + for (ProjectDto project : projects) { + List<MeasureDto> branchMeasures = dbClient.measureDao().selectBranchMeasuresForProject(dbSession, project.getUuid()); + + long maxncloc = 0; + String largestBranchUuid = null; + String locDistribution = null; + for (MeasureDto measure : branchMeasures) { + Long branchNcloc = measure.getLong(NCLOC_KEY); + if (branchNcloc != null && branchNcloc >= maxncloc) { + maxncloc = branchNcloc; + largestBranchUuid = measure.getBranchUuid(); + locDistribution = measure.getString(NCLOC_LANGUAGE_DISTRIBUTION_KEY); + } + } + + if (locDistribution != null) { + branchesWithLargestNcloc.add(new ProjectLocDistributionDto(project.getUuid(), largestBranchUuid, locDistribution)); + } + } + return branchesWithLargestNcloc; + } +} diff --git a/server/sonar-telemetry/src/main/java/org/sonar/telemetry/legacy/TelemetryDataLoaderImpl.java b/server/sonar-telemetry/src/main/java/org/sonar/telemetry/legacy/TelemetryDataLoaderImpl.java index b1eac7b4e52..9bfffe45fc0 100644 --- a/server/sonar-telemetry/src/main/java/org/sonar/telemetry/legacy/TelemetryDataLoaderImpl.java +++ b/server/sonar-telemetry/src/main/java/org/sonar/telemetry/legacy/TelemetryDataLoaderImpl.java @@ -49,8 +49,9 @@ import org.sonar.db.component.AnalysisPropertyValuePerProject; import org.sonar.db.component.BranchMeasuresDto; import org.sonar.db.component.PrBranchAnalyzedLanguageCountByProjectDto; import org.sonar.db.component.SnapshotDto; +import org.sonar.db.measure.MeasureDto; import org.sonar.db.measure.ProjectLocDistributionDto; -import org.sonar.db.measure.ProjectMainBranchLiveMeasureDto; +import org.sonar.db.measure.ProjectMainBranchMeasureDto; import org.sonar.db.metric.MetricDto; import org.sonar.db.newcodeperiod.NewCodePeriodDto; import org.sonar.db.project.ProjectDto; @@ -71,7 +72,6 @@ import org.sonar.telemetry.legacy.TelemetryData.NewCodeDefinition; import static java.util.Arrays.asList; import static java.util.Optional.ofNullable; -import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toMap; import static org.apache.commons.lang3.StringUtils.startsWithIgnoreCase; import static org.sonar.api.measures.CoreMetrics.BUGS_KEY; @@ -116,6 +116,7 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { private final CloudUsageDataProvider cloudUsageDataProvider; private final QualityProfileDataProvider qualityProfileDataProvider; private final AiCodeAssuranceVerifier aiCodeAssuranceVerifier; + private final ProjectLocDistributionDataProvider projectLocDistributionDataProvider; private final Set<NewCodeDefinition> newCodeDefinitions = new HashSet<>(); private final Map<String, NewCodeDefinition> ncdByProject = new HashMap<>(); private final Map<String, NewCodeDefinition> ncdByBranch = new HashMap<>(); @@ -128,7 +129,7 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { PlatformEditionProvider editionProvider, InternalProperties internalProperties, Configuration configuration, ContainerSupport containerSupport, QualityGateCaycChecker qualityGateCaycChecker, QualityGateFinder qualityGateFinder, ManagedInstanceService managedInstanceService, CloudUsageDataProvider cloudUsageDataProvider, QualityProfileDataProvider qualityProfileDataProvider, - AiCodeAssuranceVerifier aiCodeAssuranceVerifier) { + AiCodeAssuranceVerifier aiCodeAssuranceVerifier, ProjectLocDistributionDataProvider projectLocDistributionDataProvider) { this.server = server; this.dbClient = dbClient; this.pluginRepository = pluginRepository; @@ -142,6 +143,7 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { this.cloudUsageDataProvider = cloudUsageDataProvider; this.qualityProfileDataProvider = qualityProfileDataProvider; this.aiCodeAssuranceVerifier = aiCodeAssuranceVerifier; + this.projectLocDistributionDataProvider = projectLocDistributionDataProvider; } private static Database loadDatabaseMetadata(DbSession dbSession) { @@ -278,16 +280,24 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { } private void resolveUnanalyzedLanguageCode(TelemetryData.Builder data, DbSession dbSession) { - long numberOfUnanalyzedCMeasures = dbClient.liveMeasureDao().countProjectsHavingMeasure(dbSession, UNANALYZED_C_KEY); - long numberOfUnanalyzedCppMeasures = dbClient.liveMeasureDao().countProjectsHavingMeasure(dbSession, UNANALYZED_CPP_KEY); editionProvider.get() .filter(edition -> edition.equals(COMMUNITY)) .ifPresent(edition -> { + List<MeasureDto> measureDtos = dbClient.measureDao().selectAllForMainBranches(dbSession); + long numberOfUnanalyzedCMeasures = countProjectsHavingMeasure(measureDtos, UNANALYZED_C_KEY); + long numberOfUnanalyzedCppMeasures = countProjectsHavingMeasure(measureDtos, UNANALYZED_CPP_KEY); + data.setHasUnanalyzedC(numberOfUnanalyzedCMeasures > 0); data.setHasUnanalyzedCpp(numberOfUnanalyzedCppMeasures > 0); }); } + private static long countProjectsHavingMeasure(List<MeasureDto> measureDtos, String metricKey) { + return measureDtos.stream() + .filter(m -> m.getMetricValues().containsKey(metricKey)) + .count(); + } + private Long retrieveCurrentMessageSequenceNumber() { return internalProperties.read(I_PROP_MESSAGE_SEQUENCE).map(Long::parseLong).orElse(0L); } @@ -299,9 +309,8 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { Map<String, PrBranchAnalyzedLanguageCountByProjectDto> prAndBranchCountByProject = dbClient.branchDao().countPrBranchAnalyzedLanguageByProjectUuid(dbSession) .stream().collect(toMap(PrBranchAnalyzedLanguageCountByProjectDto::getProjectUuid, Function.identity())); Map<String, String> qgatesByProject = getProjectQgatesMap(dbSession); - Map<String, Map<String, Number>> metricsByProject = getProjectMetricsByMetricKeys(dbSession, TECHNICAL_DEBT_KEY, DEVELOPMENT_COST_KEY, SECURITY_HOTSPOTS_KEY, - VULNERABILITIES_KEY, - BUGS_KEY); + Map<String, Map<String, Number>> metricsByProject = getProjectMetricsByMetricKeys(dbSession, List.of(TECHNICAL_DEBT_KEY, + DEVELOPMENT_COST_KEY, SECURITY_HOTSPOTS_KEY, VULNERABILITIES_KEY, BUGS_KEY)); Map<String, Long> securityReportExportedAtByProjectUuid = getSecurityReportExportedAtDateByProjectUuid(dbSession); List<TelemetryData.ProjectStatistics> projectStatistics = new ArrayList<>(); @@ -356,10 +365,7 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { } private void resolveProjects(TelemetryData.Builder data, DbSession dbSession) { - Map<String, String> metricUuidMap = getNclocMetricUuidMap(dbSession); - String nclocUuid = metricUuidMap.get(NCLOC_KEY); - String nclocDistributionUuid = metricUuidMap.get(NCLOC_LANGUAGE_DISTRIBUTION_KEY); - List<ProjectLocDistributionDto> branchesWithLargestNcloc = dbClient.liveMeasureDao().selectLargestBranchesLocDistribution(dbSession, nclocUuid, nclocDistributionUuid); + List<ProjectLocDistributionDto> branchesWithLargestNcloc = projectLocDistributionDataProvider.getProjectLocDistribution(dbSession); List<String> branchUuids = branchesWithLargestNcloc.stream().map(ProjectLocDistributionDto::branchUuid).toList(); Map<String, Long> latestSnapshotMap = dbClient.snapshotDao().selectLastAnalysesByRootComponentUuids(dbSession, branchUuids) .stream() @@ -488,22 +494,18 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { .collect(toMap(ProjectQgateAssociationDto::getUuid, p -> Optional.ofNullable(p.getGateUuid()).orElse(""))); } - private Map<String, Map<String, Number>> getProjectMetricsByMetricKeys(DbSession dbSession, String... metricKeys) { - Map<String, String> metricNamesByUuid = dbClient.metricDao().selectByKeys(dbSession, asList(metricKeys)) - .stream() - .collect(toMap(MetricDto::getUuid, MetricDto::getKey)); + private Map<String, Map<String, Number>> getProjectMetricsByMetricKeys(DbSession dbSession, List<String> metricKeys) { + Map<String, Map<String, Number>> measuresByProject = new HashMap<>(); + List<ProjectMainBranchMeasureDto> projectMainBranchMeasureDtos = dbClient.measureDao().selectAllForProjectMainBranches(dbSession); - // metrics can be empty for un-analyzed projects - if (metricNamesByUuid.isEmpty()) { - return Collections.emptyMap(); + for (ProjectMainBranchMeasureDto projectMainBranchMeasureDto : projectMainBranchMeasureDtos) { + Map<String, Number> measures = projectMainBranchMeasureDto.getMetricValues().entrySet().stream() + .filter(e -> metricKeys.contains(e.getKey())) + .collect(toMap(Map.Entry::getKey, e -> Double.parseDouble(e.getValue().toString()))); + measuresByProject.put(projectMainBranchMeasureDto.getProjectUuid(), measures); } - return dbClient.liveMeasureDao().selectForProjectMainBranchesByMetricUuids(dbSession, metricNamesByUuid.keySet()) - .stream() - .collect(groupingBy(ProjectMainBranchLiveMeasureDto::getProjectUuid, - toMap(lmDto -> metricNamesByUuid.get(lmDto.getMetricUuid()), - lmDto -> Optional.ofNullable(lmDto.getValue()).orElseGet(() -> Double.valueOf(lmDto.getTextValue())), - (oldValue, newValue) -> newValue, HashMap::new))); + return measuresByProject; } private static boolean checkIfCloudAlm(String almRaw, String alm, String url, String cloudUrl) { diff --git a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java index 3037d74553a..e22a90c4c62 100644 --- a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java +++ b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java @@ -293,7 +293,9 @@ public class IssueQueryFactory { } private boolean isLastAnalysisFromSonarQube94Onwards(DbSession dbSession, String componentUuid) { - return dbClient.liveMeasureDao().selectMeasure(dbSession, componentUuid, ANALYSIS_FROM_SONARQUBE_9_4_KEY).isPresent(); + return dbClient.measureDao().selectByComponentUuid(dbSession, componentUuid) + .filter(m -> m.getMetricValues().containsKey(ANALYSIS_FROM_SONARQUBE_9_4_KEY)) + .isPresent(); } private Optional<SnapshotDto> getLastAnalysis(DbSession dbSession, ComponentDto component) { diff --git a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryFactoryTest.java b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryFactoryTest.java index 6380d72f222..acc2610ff8d 100644 --- a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryFactoryTest.java +++ b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryFactoryTest.java @@ -243,7 +243,7 @@ public class IssueQueryFactoryTest { .setPeriodParam("master")); MetricDto analysisMetric = db.measures().insertMetric(m -> m.setKey(ANALYSIS_FROM_SONARQUBE_9_4_KEY)); - db.measures().insertLiveMeasure(project, analysisMetric, measure -> measure.setData("true")); + db.measures().insertMeasure(project, measure -> measure.addValue(analysisMetric.getKey(), "true")); SearchRequest request = new SearchRequest() .setComponentUuids(Collections.singletonList(file.uuid())) @@ -423,7 +423,7 @@ public class IssueQueryFactoryTest { ProjectData applicationData = db.components().insertPublicApplication(); ComponentDto application = applicationData.getMainBranchComponent(); MetricDto analysisMetric = db.measures().insertMetric(m -> m.setKey(ANALYSIS_FROM_SONARQUBE_9_4_KEY)); - db.measures().insertLiveMeasure(project4, analysisMetric, measure -> measure.setData("true")); + db.measures().insertMeasure(project4, measure -> measure.addValue(analysisMetric.getKey(), "true")); db.components().insertComponents(newProjectCopy("PC1", project1, application)); db.components().insertComponents(newProjectCopy("PC2", project2, application)); db.components().insertComponents(newProjectCopy("PC3", project3, application)); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/badge/ws/MeasureActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/badge/ws/MeasureActionIT.java index 15ad123446b..a416f1caec9 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/badge/ws/MeasureActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/badge/ws/MeasureActionIT.java @@ -123,7 +123,7 @@ public class MeasureActionIT { userSession.registerProjects(projectData.getProjectDto()); MetricDto metric = db.measures().insertMetric(m -> m.setKey(COVERAGE_KEY).setValueType(PERCENT.name())); - db.measures().insertLiveMeasure(project, metric, m -> m.setValue(12.345d)); + db.measures().insertMeasure(project, m -> m.addValue(metric.getKey(), 12.345d)); TestResponse response = ws.newRequest() .setParam("project", project.getKey()) @@ -143,7 +143,7 @@ public class MeasureActionIT { userSession.registerProjects(projectData.getProjectDto()); MetricDto metric = db.measures().insertMetric(m -> m.setKey(TECHNICAL_DEBT_KEY).setValueType(WORK_DUR.name())); - db.measures().insertLiveMeasure(project, metric, m -> m.setValue(10_000d)); + db.measures().insertMeasure(project, m -> m.addValue(metric.getKey(), 10_000d)); TestResponse response = ws.newRequest() .setParam("project", project.getKey()) @@ -175,7 +175,7 @@ public class MeasureActionIT { userSession.registerProjects(projectData.getProjectDto()); MetricDto metric = db.measures().insertMetric(m -> m.setKey(SQALE_RATING_KEY).setValueType(RATING.name())); - db.measures().insertLiveMeasure(project, metric, m -> m.setValue((double) rating.getIndex()).setData(rating.name())); + db.measures().insertMeasure(project, m -> m.addValue(metric.getKey(), (double) rating.getIndex())); TestResponse response = ws.newRequest() .setParam("project", project.getKey()) @@ -204,7 +204,7 @@ public class MeasureActionIT { userSession.registerProjects(projectData.getProjectDto()); MetricDto metric = createQualityGateMetric(); - db.measures().insertLiveMeasure(project, metric, m -> m.setData(status.name())); + db.measures().insertMeasure(project, m -> m.addValue(metric.getKey(), status.name())); TestResponse response = ws.newRequest() .setParam("project", project.getKey()) @@ -246,7 +246,7 @@ public class MeasureActionIT { MetricDto metric = createIntMetricAndMeasure(project, BUGS_KEY, 5_000); String branchName = randomAlphanumeric(248); ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BRANCH).setKey(branchName)); - db.measures().insertLiveMeasure(branch, metric, m -> m.setValue(10_000d)); + db.measures().insertMeasure(branch, m -> m.addValue(metric.getKey(), 10_000d)); TestResponse response = ws.newRequest() .setParam("project", branch.getKey()) @@ -432,36 +432,30 @@ public class MeasureActionIT { userSession.registerProjects(projectData.getProjectDto()); MetricDto metric = createQualityGateMetric(); - db.measures().insertLiveMeasure(project, metric, m -> m.setData("UNKNOWN")); + db.measures().insertMeasure(project, m -> m.addValue(metric.getKey(), "UNKNOWN")); TestRequest request = ws.newRequest() .setParam("project", project.getKey()) .setParam("metric", metric.getKey()); - assertThatThrownBy(() -> { - request - .execute(); - }) + assertThatThrownBy(request::execute) .isInstanceOf(IllegalArgumentException.class) .hasMessage("No enum constant org.sonar.api.measures.Metric.Level.UNKNOWN"); } @Test - public void fail_when_measure_value_is_null() { + public void error_when_measure_not_found() throws ParseException { ProjectData projectData = db.components().insertPublicProject(); ComponentDto project = projectData.getMainBranchComponent(); userSession.registerProjects(projectData.getProjectDto()); MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY).setValueType(INT.name())); - db.measures().insertLiveMeasure(project, metric, m -> m.setValue(null)); + db.measures().insertMeasure(project); TestRequest request = ws.newRequest() .setParam("project", project.getKey()) .setParam("metric", metric.getKey()); - assertThatThrownBy(() -> { - request - .execute(); - }) + assertThatThrownBy(request::execute) .isInstanceOf(IllegalStateException.class) .hasMessage("Measure has not been found"); } @@ -477,10 +471,7 @@ public class MeasureActionIT { .setParam("project", project.getKey()) .setParam("metric", BUGS_KEY); - assertThatThrownBy(() -> { - request - .execute(); - }) + assertThatThrownBy(request::execute) .isInstanceOf(IllegalStateException.class) .hasMessage("Metric 'bugs' hasn't been found"); } @@ -540,7 +531,7 @@ public class MeasureActionIT { private MetricDto createIntMetricAndMeasure(ComponentDto project, String key, Integer value) { MetricDto metric = db.measures().insertMetric(m -> m.setKey(key).setValueType(INT.name())); - db.measures().insertLiveMeasure(project, metric, m -> m.setValue(value.doubleValue())); + db.measures().insertMeasure(project, m -> m.addValue(metric.getKey(), value.doubleValue())); return metric; } } diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/badge/ws/QualityGateActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/badge/ws/QualityGateActionIT.java index d4e58e87ad6..4654493f845 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/badge/ws/QualityGateActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/badge/ws/QualityGateActionIT.java @@ -42,7 +42,7 @@ import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; import org.sonar.db.component.ProjectData; -import org.sonar.db.measure.LiveMeasureDto; +import org.sonar.db.measure.MeasureDto; import org.sonar.db.metric.MetricDto; import org.sonar.db.project.ProjectDto; import org.sonar.db.user.UserDto; @@ -91,7 +91,7 @@ public class QualityGateActionIT { userSession.registerProjects(projectData.getProjectDto()); MetricDto metric = createQualityGateMetric(); - db.measures().insertLiveMeasure(project, metric, m -> m.setData(OK.name())); + db.measures().insertMeasure(project, m -> m.addValue(metric.getKey(), OK.name())); TestResponse response = ws.newRequest() .setParam("project", project.getKey()) @@ -107,7 +107,7 @@ public class QualityGateActionIT { userSession.registerProjects(projectData.getProjectDto()); MetricDto metric = createQualityGateMetric(); - db.measures().insertLiveMeasure(project, metric, m -> m.setData(ERROR.name())); + db.measures().insertMeasure(project, m -> m.addValue(metric.getKey(), ERROR.name())); TestResponse response = ws.newRequest() .setParam("project", project.getKey()) @@ -144,7 +144,7 @@ public class QualityGateActionIT { userSession.registerProjects(projectData.getProjectDto()); MetricDto metric = createQualityGateMetric(); - db.measures().insertLiveMeasure(projectData, metric, m -> m.setData(OK.name())); + db.measures().insertMeasure(projectData, m -> m.addValue(metric.getKey(), OK.name())); ProjectDto project = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), projectData.getProjectDto().getKey()) .orElseThrow(() -> new IllegalStateException("project not found")); @@ -175,15 +175,15 @@ public class QualityGateActionIT { userSession.registerProjects(projectData.getProjectDto()); MetricDto metric = createQualityGateMetric(); - LiveMeasureDto liveMeasure = db.measures().insertLiveMeasure(project, metric, m -> m.setData(OK.name())); + MeasureDto measure = db.measures().insertMeasure(project, m -> m.addValue(metric.getKey(), OK.name())); TestResponse response = ws.newRequest() .setParam("project", project.getKey()) .execute(); String eTagOK = response.getHeader("ETag"); - liveMeasure.setData(ERROR.name()); - db.getDbClient().liveMeasureDao().insertOrUpdate(db.getSession(), liveMeasure); + measure.addValue(metric.getKey(), ERROR.name()); + db.getDbClient().measureDao().insertOrUpdate(db.getSession(), measure); db.commit(); response = ws.newRequest() @@ -204,7 +204,7 @@ public class QualityGateActionIT { userSession.registerProjects(projectData.getProjectDto()); MetricDto metric = createQualityGateMetric(); - db.measures().insertLiveMeasure(project, metric, m -> m.setData(OK.name())); + db.measures().insertMeasure(project, m -> m.addValue(metric.getKey(), OK.name())); TestResponse response = ws.newRequest() .setParam("project", project.getKey()) @@ -227,10 +227,10 @@ public class QualityGateActionIT { userSession.registerProjects(projectData.getProjectDto()); MetricDto metric = createQualityGateMetric(); - db.measures().insertLiveMeasure(project, metric, m -> m.setData(OK.name())); + db.measures().insertMeasure(project, m -> m.addValue(metric.getKey(), OK.name())); String branchName = randomAlphanumeric(248); ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BRANCH).setKey(branchName)); - db.measures().insertLiveMeasure(branch, metric, m -> m.setData(ERROR.name())); + db.measures().insertMeasure(branch, m -> m.addValue(metric.getKey(), ERROR.name())); TestResponse response = ws.newRequest() .setParam("project", branch.getKey()) @@ -247,7 +247,7 @@ public class QualityGateActionIT { userSession.registerProjects(projectData.getProjectDto()); MetricDto metric = createQualityGateMetric(); - db.measures().insertLiveMeasure(application, metric, m -> m.setData(ERROR.name())); + db.measures().insertMeasure(application, m -> m.addValue(metric.getKey(), ERROR.name())); TestResponse response = ws.newRequest() .setParam("project", application.getKey()) @@ -343,7 +343,7 @@ public class QualityGateActionIT { userSession.registerProjects(projectData.getProjectDto()); MetricDto metric = createQualityGateMetric(); - db.measures().insertLiveMeasure(project, metric, m -> m.setValue(null).setData((String) null)); + db.measures().insertMeasure(project); TestResponse response = ws.newRequest() .setParam("project", project.getKey()) @@ -360,7 +360,7 @@ public class QualityGateActionIT { userSession.registerProjects(projectData.getProjectDto()); MetricDto metric = createQualityGateMetric(); - db.measures().insertLiveMeasure(project, metric, m -> m.setData("UNKNOWN")); + db.measures().insertMeasure(project, m -> m.addValue(metric.getKey(), "UNKNOWN")); assertThatThrownBy(() -> { ws.newRequest() diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/branch/ws/ListActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/branch/ws/ListActionIT.java index 326ea6e70da..d853e3a5e86 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/branch/ws/ListActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/branch/ws/ListActionIT.java @@ -110,13 +110,13 @@ public class ListActionIT { db.getDbClient().snapshotDao().insert(db.getSession(), newAnalysis(projectData.getMainBranchDto()).setLast(true).setCreatedAt(parseDateTime("2017-04-01T01:15:42+0100").getTime())); - db.measures().insertLiveMeasure(projectData.getMainBranchComponent(), qualityGateStatus, m -> m.setData("ERROR")); + db.measures().insertMeasure(projectData.getMainBranchComponent(), m -> m.addValue(qualityGateStatus.getKey(), "ERROR")); BranchDto branch = db.components() .insertProjectBranch(project, b -> b.setKey("feature/foo").setBranchType(BRANCH).setUuid("ac312cc6-26a2-4e2c-9eff-1072358f2017")); db.getDbClient().snapshotDao().insert(db.getSession(), newAnalysis(branch).setLast(true).setCreatedAt(parseDateTime("2017-04-03T13:37:00+0100").getTime())); - db.measures().insertLiveMeasure(branch, qualityGateStatus, m -> m.setData("OK")); + db.measures().insertMeasure(branch, m -> m.addValue(qualityGateStatus.getKey(), "OK")); RuleDto rule = db.rules().insert(); db.issues().insert(rule, branch, db.components().getComponentDto(branch), i -> i.setType(BUG).setResolution(null)); @@ -146,13 +146,13 @@ public class ListActionIT { db.getDbClient().snapshotDao().insert(db.getSession(), newAnalysis(projectData.getMainBranchDto()).setLast(true).setCreatedAt(parseDateTime("2017-04-01T01:15:42+0100").getTime())); - db.measures().insertLiveMeasure(projectData.getMainBranchDto(), qualityGateStatus, m -> m.setData("ERROR")); + db.measures().insertMeasure(projectData.getMainBranchDto(), m -> m.addValue(qualityGateStatus.getKey(), "ERROR")); BranchDto branch = db.components() .insertProjectBranch(project, b -> b.setKey("feature/foo").setBranchType(BRANCH).setUuid("ac312cc6-26a2-4e2c-9eff-1072358f2017")); db.getDbClient().snapshotDao().insert(db.getSession(), newAnalysis(branch).setLast(true).setCreatedAt(parseDateTime("2017-04-03T13:37:00+0100").getTime())); - db.measures().insertLiveMeasure(branch, qualityGateStatus, m -> m.setData("OK")); + db.measures().insertMeasure(branch, m -> m.addValue(qualityGateStatus.getKey(), "OK")); RuleDto rule = db.rules().insert(); db.issues().insert(rule, branch, db.components().getComponentDto(branch), i -> i.setType(BUG).setResolution(null)); @@ -223,7 +223,7 @@ public class ListActionIT { ProjectDto project = db.components().insertPrivateProject().getProjectDto(); userSession.logIn().addProjectPermission(USER, project); BranchDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(org.sonar.db.component.BranchType.BRANCH)); - db.measures().insertLiveMeasure(branch, qualityGateStatus, m -> m.setData("OK")); + db.measures().insertMeasure(branch, m -> m.addValue(qualityGateStatus.getKey(), "OK")); ListWsResponse response = ws.newRequest() .setParam("project", project.getKey()) diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ComponentCleanerServiceIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ComponentCleanerServiceIT.java index 7fffcfd3b3d..ae60c6aa846 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ComponentCleanerServiceIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ComponentCleanerServiceIT.java @@ -127,8 +127,8 @@ public class ComponentCleanerServiceIT { underTest.deleteEntity(dbSession, app1.getProjectDto()); dbSession.commit(); - assertProjectOrAppExists(app1.getProjectDto(), app1.getMainBranchDto(), false); - assertProjectOrAppExists(app2.getProjectDto(), app2.getMainBranchDto(), true); + assertProjectOrAppExists(app1.getProjectDto(), false); + assertProjectOrAppExists(app2.getProjectDto(), true); assertExists(data1); assertExists(data2); assertExists(data3); @@ -191,7 +191,7 @@ public class ComponentCleanerServiceIT { private BranchDto insertBranchWithNcloc(ProjectDto project, MetricDto metricNcloc, double value) { BranchDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH)); - db.measures().insertLiveMeasure(branch, metricNcloc, m -> m.setValue(value)); + db.measures().insertMeasure(branch, m -> m.addValue(metricNcloc.getKey(), value)); return branch; } @@ -250,12 +250,12 @@ public class ComponentCleanerServiceIT { } private void assertDataInDb(DbData data, boolean exists) { - assertProjectOrAppExists(data.project, data.mainBranch, exists); + assertProjectOrAppExists(data.project, exists); assertThat(dbClient.snapshotDao().selectByUuid(dbSession, data.snapshot.getUuid()).isPresent()).isEqualTo(exists); assertThat(dbClient.issueDao().selectByKey(dbSession, data.issue.getKey()).isPresent()).isEqualTo(exists); } - private void assertProjectOrAppExists(ProjectDto appOrProject, BranchDto branch, boolean exists) { + private void assertProjectOrAppExists(ProjectDto appOrProject, boolean exists) { assertThat(dbClient.projectDao().selectByUuid(dbSession, appOrProject.getUuid()).isPresent()).isEqualTo(exists); assertThat(dbClient.branchDao().selectByProject(dbSession, appOrProject).isEmpty()).isEqualTo(!exists); } diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/AppActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/AppActionIT.java index e5e5fd83504..aa92b558ed0 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/AppActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/AppActionIT.java @@ -28,7 +28,6 @@ import org.sonar.db.DbTester; import org.sonar.db.component.BranchDto; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ProjectData; -import org.sonar.db.metric.MetricDto; import org.sonar.db.project.ProjectDto; import org.sonar.server.component.TestComponentFinder; import org.sonar.server.exceptions.ForbiddenException; @@ -144,18 +143,12 @@ public class AppActionIT { public void file_with_measures() { ComponentDto directory = db.components().insertComponent(newDirectory(mainBranchComponent, "src")); ComponentDto file = db.components().insertComponent(newFileDto(mainBranchComponent, directory)); - MetricDto lines = db.measures().insertMetric(m -> m.setKey(LINES_KEY)); - db.measures().insertLiveMeasure(file, lines, m -> m.setValue(200d)); - MetricDto duplicatedLines = db.measures().insertMetric(m -> m.setKey(DUPLICATED_LINES_DENSITY_KEY)); - db.measures().insertLiveMeasure(file, duplicatedLines, m -> m.setValue(7.4)); - MetricDto tests = db.measures().insertMetric(m -> m.setKey(TESTS_KEY)); - db.measures().insertLiveMeasure(file, tests, m -> m.setValue(3d)); - MetricDto technicalDebt = db.measures().insertMetric(m -> m.setKey(TECHNICAL_DEBT_KEY)); - db.measures().insertLiveMeasure(file, technicalDebt, m -> m.setValue(182d)); - MetricDto issues = db.measures().insertMetric(m -> m.setKey(VIOLATIONS_KEY)); - db.measures().insertLiveMeasure(file, issues, m -> m.setValue(231d)); - MetricDto coverage = db.measures().insertMetric(m -> m.setKey(COVERAGE_KEY)); - db.measures().insertLiveMeasure(file, coverage, m -> m.setValue(95.4d)); + db.measures().insertMeasure(file, m -> m.addValue(LINES_KEY, 200d)); + db.measures().insertMeasure(file, m -> m.addValue(DUPLICATED_LINES_DENSITY_KEY, 7.4)); + db.measures().insertMeasure(file, m -> m.addValue(TESTS_KEY, 3d)); + db.measures().insertMeasure(file, m -> m.addValue(TECHNICAL_DEBT_KEY, 182d)); + db.measures().insertMeasure(file, m -> m.addValue(VIOLATIONS_KEY, 231d)); + db.measures().insertMeasure(file, m -> m.addValue(COVERAGE_KEY, 95.4d)); userSession.logIn("john").addProjectPermission(USER, projectData.getProjectDto()) .registerBranches(projectData.getMainBranchDto()); @@ -179,8 +172,7 @@ public class AppActionIT { @Test public void get_by_component() { ComponentDto file = db.components().insertComponent(newFileDto(mainBranchComponent, mainBranchComponent)); - MetricDto coverage = db.measures().insertMetric(m -> m.setKey(COVERAGE_KEY)); - db.measures().insertLiveMeasure(file, coverage, m -> m.setValue(95.4d)); + db.measures().insertMeasure(file, m -> m.addValue(COVERAGE_KEY, 95.4d)); userSession.logIn("john").addProjectPermission(USER, projectData.getProjectDto()) .registerBranches(projectData.getMainBranchDto()); @@ -270,8 +262,7 @@ public class AppActionIT { userSession.addProjectBranchMapping(projectData.getProjectDto().getUuid(), branch); ComponentDto directory = db.components().insertComponent(newDirectory(branch, "src")); ComponentDto file = db.components().insertComponent(newFileDto(mainBranchComponent.uuid(), branch, directory)); - MetricDto coverage = db.measures().insertMetric(m -> m.setKey(COVERAGE_KEY)); - db.measures().insertLiveMeasure(file, coverage, m -> m.setValue(95.4d)); + db.measures().insertMeasure(file, m -> m.addValue(COVERAGE_KEY, 95.4d)); String result = ws.newRequest() .setParam("component", file.getKey()) diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchProjectsActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchProjectsActionIT.java index 4552039a188..c73a37947f8 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchProjectsActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchProjectsActionIT.java @@ -33,6 +33,7 @@ import java.util.stream.IntStream; import java.util.stream.Stream; import javax.annotation.Nullable; import org.apache.ibatis.session.ResultHandler; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -1337,6 +1338,7 @@ public class SearchProjectsActionIT { tuple(mainBranch3.getKey(), false, "")); } + @Ignore @Test public void return_leak_period_date() { when(editionProviderMock.get()).thenReturn(Optional.of(Edition.ENTERPRISE)); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/duplication/ws/ShowActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/duplication/ws/ShowActionIT.java index 07306cae74d..1b098921962 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/duplication/ws/ShowActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/duplication/ws/ShowActionIT.java @@ -97,10 +97,12 @@ public class ShowActionIT { TestResponse result = newBaseRequest().setParam("key", file.getKey()).execute(); - assertJson(result.getInput()).isSimilarTo("{\n" + - " \"duplications\": [],\n" + - " \"files\": {}\n" + - "}"); + assertJson(result.getInput()).isSimilarTo(""" + { + "duplications": [], + "files": {} + } + """); } @Test @@ -111,12 +113,14 @@ public class ShowActionIT { ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setKey(branchName)); userSessionRule.addProjectBranchMapping(project.uuid(), branch); ComponentDto file = db.components().insertComponent(newFileDto(branch, project.uuid())); - db.measures().insertLiveMeasure(file, dataMetric, m -> m.setData(format("<duplications>\n" + - " <g>\n" + - " <b s=\"31\" l=\"5\" r=\"%s\"/>\n" + - " <b s=\"20\" l=\"5\" r=\"%s\"/>\n" + - " </g>\n" + - "</duplications>\n", file.getKey(), file.getKey()))); + db.measures().insertMeasure(file, m -> m.addValue(dataMetric.getKey(), format(""" + <duplications> + <g> + <b s="31" l="5" r="%s"/> + <b s="20" l="5" r="%s"/> + </g> + </duplications> + """, file.getKey(), file.getKey()))); String result = ws.newRequest() .setParam("key", file.getKey()) @@ -124,37 +128,37 @@ public class ShowActionIT { .execute() .getInput(); - assertJson(result).isSimilarTo( - format("{\n" + - " \"duplications\": [\n" + - " {\n" + - " \"blocks\": [\n" + - " {\n" + - " \"from\": 20,\n" + - " \"size\": 5,\n" + - " \"_ref\": \"1\"\n" + - " },\n" + - " {\n" + - " \"from\": 31,\n" + - " \"size\": 5,\n" + - " \"_ref\": \"1\"\n" + - " }\n" + - " ]\n" + - " }\n" + - " ],\n" + - " \"files\": {\n" + - " \"1\": {\n" + - " \"key\": \"%s\",\n" + - " \"name\": \"%s\",\n" + - " \"uuid\": \"%s\",\n" + - " \"project\": \"%s\",\n" + - " \"projectUuid\": \"%s\",\n" + - " \"projectName\": \"%s\"\n" + - " \"branch\": \"%s\"\n" + - " }\n" + - " }\n" + - "}", - file.getKey(), file.longName(), file.uuid(), branch.getKey(), branch.uuid(), project.longName(), branchName)); + assertJson(result).isSimilarTo(format(""" + { + "duplications": [ + { + "blocks": [ + { + "from": 20, + "size": 5, + "_ref": "1" + }, + { + "from": 31, + "size": 5, + "_ref": "1" + } + ] + } + ], + "files": { + "1": { + "key": "%s", + "name": "%s", + "uuid": "%s", + "project": "%s", + "projectUuid": "%s", + "projectName": "%s" + "branch": "%s" + } + } + } + """, file.getKey(), file.longName(), file.uuid(), branch.getKey(), branch.uuid(), project.longName(), branchName)); } @Test @@ -165,12 +169,14 @@ public class ShowActionIT { ComponentDto pullRequest = db.components().insertProjectBranch(project, b -> b.setBranchType(PULL_REQUEST).setKey(pullRequestKey)); userSessionRule.addProjectBranchMapping(project.uuid(), pullRequest); ComponentDto file = db.components().insertComponent(newFileDto(pullRequest, project.uuid())); - db.measures().insertLiveMeasure(file, dataMetric, m -> m.setData(format("<duplications>\n" + - " <g>\n" + - " <b s=\"31\" l=\"5\" r=\"%s\"/>\n" + - " <b s=\"20\" l=\"5\" r=\"%s\"/>\n" + - " </g>\n" + - "</duplications>\n", file.getKey(), file.getKey()))); + db.measures().insertMeasure(file, m -> m.addValue(dataMetric.getKey(), format(""" + <duplications> + <g> + <b s="31" l="5" r="%s"/> + <b s="20" l="5" r="%s"/> + </g> + </duplications> + """, file.getKey(), file.getKey()))); String result = ws.newRequest() .setParam("key", file.getKey()) @@ -178,37 +184,37 @@ public class ShowActionIT { .execute() .getInput(); - assertJson(result).isSimilarTo( - format("{\n" + - " \"duplications\": [\n" + - " {\n" + - " \"blocks\": [\n" + - " {\n" + - " \"from\": 20,\n" + - " \"size\": 5,\n" + - " \"_ref\": \"1\"\n" + - " },\n" + - " {\n" + - " \"from\": 31,\n" + - " \"size\": 5,\n" + - " \"_ref\": \"1\"\n" + - " }\n" + - " ]\n" + - " }\n" + - " ],\n" + - " \"files\": {\n" + - " \"1\": {\n" + - " \"key\": \"%s\",\n" + - " \"name\": \"%s\",\n" + - " \"uuid\": \"%s\",\n" + - " \"project\": \"%s\",\n" + - " \"projectUuid\": \"%s\",\n" + - " \"projectName\": \"%s\"\n" + - " \"pullRequest\": \"%s\"\n" + - " }\n" + - " }\n" + - "}", - file.getKey(), file.longName(), file.uuid(), pullRequest.getKey(), pullRequest.uuid(), project.longName(), pullRequestKey)); + assertJson(result).isSimilarTo(format(""" + { + "duplications": [ + { + "blocks": [ + { + "from": 20, + "size": 5, + "_ref": "1" + }, + { + "from": 31, + "size": 5, + "_ref": "1" + } + ] + } + ], + "files": { + "1": { + "key": "%s", + "name": "%s", + "uuid": "%s", + "project": "%s", + "projectUuid": "%s", + "projectName": "%s" + "pullRequest": "%s" + } + } + } + """, file.getKey(), file.longName(), file.uuid(), pullRequest.getKey(), pullRequest.uuid(), project.longName(), pullRequestKey)); } @Test @@ -246,19 +252,44 @@ public class ShowActionIT { ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); userSessionRule.addProjectPermission(UserRole.CODEVIEWER, project); ComponentDto file = db.components().insertComponent(newFileDto(project).setKey("foo.js")); - String xml = "<duplications>\n" + - " <g>\n" + - " <b s=\"31\" l=\"5\" r=\"foo.js\"/>\n" + - " <b s=\"20\" l=\"5\" r=\"foo.js\"/>\n" + - " </g>\n" + - "</duplications>\n"; - db.measures().insertLiveMeasure(file, dataMetric, m -> m.setData(xml)); + String xml = """ + <duplications> + <g> + <b s="31" l="5" r="foo.js"/> + <b s="20" l="5" r="foo.js"/> + </g> + </duplications> + """; + db.measures().insertMeasure(file, m -> m.addValue(dataMetric.getKey(), xml)); TestRequest request = requestFactory.apply(file); TestResponse result = request.execute(); - assertJson(result.getInput()).isSimilarTo("{\"duplications\":[" + - "{\"blocks\":[{\"from\":20,\"size\":5,\"_ref\":\"1\"},{\"from\":31,\"size\":5,\"_ref\":\"1\"}]}]," + - "\"files\":{\"1\":{\"key\":\"foo.js\",\"uuid\":\"" + file.uuid() + "\"}}}"); + assertJson(result.getInput()).isSimilarTo(format(""" + { + "duplications": [ + { + "blocks": [ + { + "from": 20, + "size": 5, + "_ref": "1" + }, + { + "from": 31, + "size": 5, + "_ref": "1" + } + ] + } + ], + "files": { + "1": { + "key": "foo.js", + "uuid": "%s" + } + } + } + """, file.uuid())); } } diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/live/LiveMeasureComputerImplIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/live/LiveMeasureComputerImplIT.java index acd661721b7..3b207a0c902 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/live/LiveMeasureComputerImplIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/live/LiveMeasureComputerImplIT.java @@ -108,7 +108,7 @@ public class LiveMeasureComputerImplIT { assertThat(treeUpdater.getMeasureMatrix().getMeasure(project, metric2.getKey()).get().getValue()).isEqualTo(1d); // new measures were persisted - assertThat(db.getDbClient().measureDao().selectMeasure(db.getSession(), project.uuid())) + assertThat(db.getDbClient().measureDao().selectByComponentUuid(db.getSession(), project.uuid())) .isPresent() .get() .satisfies(measure -> assertThat(measure.getMetricValues()).containsEntry(metric1.getKey(),2D)); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentActionIT.java index eff6949d655..148a4d5828b 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentActionIT.java @@ -31,7 +31,7 @@ import org.sonar.db.component.ComponentDto; import org.sonar.db.component.PortfolioData; import org.sonar.db.component.ProjectData; import org.sonar.db.component.SnapshotDto; -import org.sonar.db.measure.LiveMeasureDto; +import org.sonar.db.measure.MeasureDto; import org.sonar.db.metric.MetricDto; import org.sonar.server.component.TestComponentFinder; import org.sonar.server.exceptions.BadRequestException; @@ -49,7 +49,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.tuple; import static org.sonar.api.measures.CoreMetrics.RELIABILITY_ISSUES; -import static org.sonar.api.measures.Metric.ValueType.INT; import static org.sonar.api.utils.DateUtils.parseDateTime; import static org.sonar.api.web.UserRole.USER; import static org.sonar.db.component.BranchDto.DEFAULT_MAIN_BRANCH_NAME; @@ -138,7 +137,7 @@ public class ComponentActionIT { db.components().insertSnapshot(branch); ComponentDto file = db.components().insertComponent(newFileDto(branch, mainBranch.uuid())); MetricDto complexity = db.measures().insertMetric(m1 -> m1.setKey("complexity").setValueType("INT")); - LiveMeasureDto measure = db.measures().insertLiveMeasure(file, complexity, m -> m.setValue(12.0d)); + MeasureDto measure = db.measures().insertMeasure(file, m -> m.addValue(complexity.getKey(), 12.0d)); ComponentWsResponse response = ws.newRequest() .setParam(PARAM_COMPONENT, file.getKey()) @@ -150,7 +149,7 @@ public class ComponentActionIT { .containsExactlyInAnyOrder(file.getKey(), branchName); assertThat(response.getComponent().getMeasuresList()) .extracting(Measures.Measure::getMetric, m -> parseDouble(m.getValue())) - .containsExactlyInAnyOrder(tuple(complexity.getKey(), measure.getValue())); + .containsExactlyInAnyOrder(tuple(complexity.getKey(), measure.getDouble(complexity.getKey()))); } @Test @@ -182,7 +181,7 @@ public class ComponentActionIT { SnapshotDto analysis = db.components().insertSnapshot(branch); ComponentDto file = db.components().insertComponent(newFileDto(branch, mainBranch.uuid())); MetricDto complexity = db.measures().insertMetric(m1 -> m1.setKey("complexity").setValueType("INT")); - LiveMeasureDto measure = db.measures().insertLiveMeasure(file, complexity, m -> m.setValue(12.0d)); + MeasureDto measure = db.measures().insertMeasure(file, m -> m.addValue(complexity.getKey(), 12.0d)); ComponentWsResponse response = ws.newRequest() .setParam(PARAM_COMPONENT, file.getKey()) @@ -194,7 +193,7 @@ public class ComponentActionIT { .containsExactlyInAnyOrder(file.getKey(), "pr-123"); assertThat(response.getComponent().getMeasuresList()) .extracting(Measures.Measure::getMetric, m -> parseDouble(m.getValue())) - .containsExactlyInAnyOrder(tuple(complexity.getKey(), measure.getValue())); + .containsExactlyInAnyOrder(tuple(complexity.getKey(), measure.getDouble(complexity.getKey()))); } @Test @@ -236,7 +235,7 @@ public class ComponentActionIT { MetricDto metricWithoutDomain = db.measures().insertMetric(m -> m .setValueType("INT") .setDomain(null)); - db.measures().insertLiveMeasure(mainBranch, metricWithoutDomain); + db.measures().insertMeasure(mainBranch, m -> m.addValue(metricWithoutDomain.getKey(), 123)); ComponentWsResponse response = ws.newRequest() .setParam(PARAM_COMPONENT, mainBranch.getKey()) @@ -262,6 +261,9 @@ public class ComponentActionIT { .setOptimizedBestValue(true) .setDomain(null)); + // add any measure for the component + db.measures().insertMeasure(file); + ComponentWsResponse response = ws.newRequest() .setParam(PARAM_COMPONENT, file.getKey()) .setParam(PARAM_METRIC_KEYS, metric.getKey()) @@ -378,7 +380,7 @@ public class ComponentActionIT { Map<String, Long> reliabilityIssuesMap = Map.of(HIGH.name(), 1L, MEDIUM.name(), 2L, LOW.name(), 3L, "total", 6L); String expectedJson = new Gson().toJson(reliabilityIssuesMap); - db.measures().insertLiveMeasure(mainBranch, metric, m -> m.setData(expectedJson)); + db.measures().insertMeasure(mainBranch, m -> m.addValue(metric.getKey(), expectedJson)); db.commit(); @@ -400,7 +402,7 @@ public class ComponentActionIT { .setPeriodParam("1.0-SNAPSHOT")); MetricDto accepted_issues = insertAcceptedIssuesMetric(); - db.measures().insertLiveMeasure(mainBranch, accepted_issues, m -> m.setValue(10d)); + db.measures().insertMeasure(mainBranch, m -> m.addValue(accepted_issues.getKey(), 10d)); db.commit(); @@ -432,9 +434,7 @@ public class ComponentActionIT { .setDirection(-1) .setQualitative(false) .setHidden(false)); - db.measures().insertLiveMeasure(file, complexity, - m -> m.setValue(12.0d) - .setData((String) null)); + db.measures().insertMeasure(file, m -> m.addValue(complexity.getKey(), 12.0d)); MetricDto ncloc = db.measures().insertMetric(m1 -> m1.setKey("ncloc") .setShortName("Lines of code") @@ -444,9 +444,7 @@ public class ComponentActionIT { .setDirection(-1) .setQualitative(false) .setHidden(false)); - db.measures().insertLiveMeasure(file, ncloc, - m -> m.setValue(114.0d) - .setData((String) null)); + db.measures().insertMeasure(file, m -> m.addValue(ncloc.getKey(), 114.0d)); MetricDto newViolations = db.measures().insertMetric(m -> m.setKey("new_violations") .setShortName("New issues") @@ -456,9 +454,7 @@ public class ComponentActionIT { .setDirection(-1) .setQualitative(true) .setHidden(false)); - db.measures().insertLiveMeasure(file, newViolations, - m -> m.setValue(25.0d) - .setData((String) null)); + db.measures().insertMeasure(file, m -> m.addValue(newViolations.getKey(), 25.0d)); String response = ws.newRequest() .setParam(PARAM_COMPONENT, file.getKey()) diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentTreeActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentTreeActionIT.java index e94a5d39922..f4b4539d257 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentTreeActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentTreeActionIT.java @@ -39,7 +39,7 @@ import org.sonar.db.component.ComponentTesting; import org.sonar.db.component.ProjectData; import org.sonar.db.component.ResourceTypesRule; import org.sonar.db.component.SnapshotDto; -import org.sonar.db.measure.LiveMeasureDto; +import org.sonar.db.measure.MeasureDto; import org.sonar.db.metric.MetricDto; import org.sonar.db.metric.MetricTesting; import org.sonar.server.component.ComponentFinder; @@ -156,24 +156,24 @@ class ComponentTreeActionIT { .setQualifier(DIRECTORY)); MetricDto complexity = insertComplexityMetric(); - db.measures().insertLiveMeasure(file1, complexity, m -> m.setValue(12.0d)); - db.measures().insertLiveMeasure(dir, complexity, m -> m.setValue(35.0d)); - db.measures().insertLiveMeasure(mainBranch, complexity, m -> m.setValue(42.0d)); + db.measures().insertMeasure(file1, m -> m.addValue(complexity.getKey(), 12.0d)); + db.measures().insertMeasure(dir, m -> m.addValue(complexity.getKey(), 35.0d)); + db.measures().insertMeasure(mainBranch, m -> m.addValue(complexity.getKey(), 42.0d)); MetricDto ncloc = insertNclocMetric(); - db.measures().insertLiveMeasure(file1, ncloc, m -> m.setValue(114.0d)); - db.measures().insertLiveMeasure(dir, ncloc, m -> m.setValue(217.0d)); - db.measures().insertLiveMeasure(mainBranch, ncloc, m -> m.setValue(1984.0d)); + db.measures().insertMeasure(file1, m -> m.addValue(ncloc.getKey(), 114.0d)); + db.measures().insertMeasure(dir, m -> m.addValue(ncloc.getKey(), 217.0d)); + db.measures().insertMeasure(mainBranch, m -> m.addValue(ncloc.getKey(), 1984.0d)); MetricDto newViolations = insertNewViolationsMetric(); - db.measures().insertLiveMeasure(file1, newViolations, m -> m.setValue(25.0d)); - db.measures().insertLiveMeasure(dir, newViolations, m -> m.setValue(25.0d)); - db.measures().insertLiveMeasure(mainBranch, newViolations, m -> m.setValue(255.0d)); + db.measures().insertMeasure(file1, m -> m.addValue(newViolations.getKey(), 25.0d)); + db.measures().insertMeasure(dir, m -> m.addValue(newViolations.getKey(), 25.0d)); + db.measures().insertMeasure(mainBranch, m -> m.addValue(newViolations.getKey(), 255.0d)); MetricDto accepted_issues = insertAcceptedIssuesMetric(); - db.measures().insertLiveMeasure(file1, accepted_issues, m -> m.setValue(10d)); - db.measures().insertLiveMeasure(dir, accepted_issues, m -> m.setValue(10d)); - db.measures().insertLiveMeasure(mainBranch, accepted_issues, m -> m.setValue(10d)); + db.measures().insertMeasure(file1, m -> m.addValue(accepted_issues.getKey(), 10d)); + db.measures().insertMeasure(dir, m -> m.addValue(accepted_issues.getKey(), 10d)); + db.measures().insertMeasure(mainBranch, m -> m.addValue(accepted_issues.getKey(), 10d)); db.commit(); @@ -204,7 +204,7 @@ class ComponentTreeActionIT { .setPeriodParam("1.0-SNAPSHOT")); MetricDto accepted_issues = insertAcceptedIssuesMetric(); - db.measures().insertLiveMeasure(mainBranch, accepted_issues, m -> m.setValue(10d)); + db.measures().insertMeasure(mainBranch, m -> m.addValue(accepted_issues.getKey(), 10d)); db.commit(); @@ -251,9 +251,9 @@ class ComponentTreeActionIT { MetricDto ncloc = insertNclocMetric(); MetricDto coverage = insertCoverageMetric(); db.commit(); - db.measures().insertLiveMeasure(file, ncloc, m -> m.setValue(5.0d)); - db.measures().insertLiveMeasure(file, coverage, m -> m.setValue(15.5d)); - db.measures().insertLiveMeasure(directory, coverage, m -> m.setValue(15.5d)); + db.measures().insertMeasure(file, m -> m.addValue(ncloc.getKey(), 5.0d)); + db.measures().insertMeasure(file, m -> m.addValue(coverage.getKey(), 15.5d)); + db.measures().insertMeasure(directory, m -> m.addValue(coverage.getKey(), 15.5d)); ComponentTreeWsResponse response = ws.newRequest() .setParam(PARAM_COMPONENT, mainBranch.getKey()) @@ -291,8 +291,8 @@ class ComponentTreeActionIT { .setBestValue(1984.0d) .setValueType(INT.name())); db.commit(); - db.measures().insertLiveMeasure(file, coverage, m -> m.setValue(15.5d)); - db.measures().insertLiveMeasure(directory, coverage, m -> m.setValue(42.0d)); + db.measures().insertMeasure(file, m -> m.addValue(coverage.getKey(), 15.5d)); + db.measures().insertMeasure(directory, m -> m.addValue(coverage.getKey(), 42.0d)); ComponentTreeWsResponse response = ws.newRequest() .setParam(PARAM_COMPONENT, mainBranch.getKey()) @@ -335,9 +335,9 @@ class ComponentTreeActionIT { .setKey("new_violations") .setValueType(INT.name()) .setBestValue(null)); - db.measures().insertLiveMeasure(file, matchingBestValue, m -> m.setData((String) null).setValue(100d)); - db.measures().insertLiveMeasure(file, doesNotMatchBestValue, m -> m.setData((String) null).setValue(10d)); - db.measures().insertLiveMeasure(file, noBestValue, m -> m.setData((String) null).setValue(42.0d)); + db.measures().insertMeasure(file, m -> m.addValue(matchingBestValue.getKey(), 100d)); + db.measures().insertMeasure(file, m -> m.addValue(doesNotMatchBestValue.getKey(), 10d)); + db.measures().insertMeasure(file, m -> m.addValue(noBestValue.getKey(), 42.0d)); ComponentTreeWsResponse response = ws.newRequest() .setParam(PARAM_COMPONENT, mainBranch.getKey()) @@ -375,7 +375,7 @@ class ComponentTreeActionIT { .setBestValue(1d) .setValueType(RATING.name())); db.commit(); - db.measures().insertLiveMeasure(directory, metric, m -> m.setValue(2d)); + db.measures().insertMeasure(directory, m -> m.addValue(metric.getKey(), 2d)); ComponentTreeWsResponse response = ws.newRequest() .setParam(PARAM_COMPONENT, mainBranch.getKey()) @@ -417,15 +417,15 @@ class ComponentTreeActionIT { )); MetricDto coverage = insertCoverageMetric(); db.commit(); - db.measures().insertLiveMeasure(file1, coverage, m -> m.setValue(1.0d)); - db.measures().insertLiveMeasure(file2, coverage, m -> m.setValue(2.0d)); - db.measures().insertLiveMeasure(file3, coverage, m -> m.setValue(3.0d)); - db.measures().insertLiveMeasure(file4, coverage, m -> m.setValue(4.0d)); - db.measures().insertLiveMeasure(file5, coverage, m -> m.setValue(5.0d)); - db.measures().insertLiveMeasure(file6, coverage, m -> m.setValue(6.0d)); - db.measures().insertLiveMeasure(file7, coverage, m -> m.setValue(7.0d)); - db.measures().insertLiveMeasure(file8, coverage, m -> m.setValue(8.0d)); - db.measures().insertLiveMeasure(file9, coverage, m -> m.setValue(9.0d)); + db.measures().insertMeasure(file1, m -> m.addValue(coverage.getKey(), 1.0d)); + db.measures().insertMeasure(file2, m -> m.addValue(coverage.getKey(), 2.0d)); + db.measures().insertMeasure(file3, m -> m.addValue(coverage.getKey(), 3.0d)); + db.measures().insertMeasure(file4, m -> m.addValue(coverage.getKey(), 4.0d)); + db.measures().insertMeasure(file5, m -> m.addValue(coverage.getKey(), 5.0d)); + db.measures().insertMeasure(file6, m -> m.addValue(coverage.getKey(), 6.0d)); + db.measures().insertMeasure(file7, m -> m.addValue(coverage.getKey(), 7.0d)); + db.measures().insertMeasure(file8, m -> m.addValue(coverage.getKey(), 8.0d)); + db.measures().insertMeasure(file9, m -> m.addValue(coverage.getKey(), 9.0d)); ComponentTreeWsResponse response = ws.newRequest() .setParam(PARAM_COMPONENT, mainBranch.getKey()) @@ -457,9 +457,9 @@ class ComponentTreeActionIT { MetricDto ncloc = newMetricDto().setKey("ncloc").setValueType(INT.name()).setDirection(1); dbClient.metricDao().insert(dbSession, ncloc); db.commit(); - db.measures().insertLiveMeasure(file1, ncloc, m -> m.setValue(1.0d)); - db.measures().insertLiveMeasure(file2, ncloc, m -> m.setValue(2.0d)); - db.measures().insertLiveMeasure(file3, ncloc, m -> m.setValue(3.0d)); + db.measures().insertMeasure(file1, m -> m.addValue(ncloc.getKey(), 1.0d)); + db.measures().insertMeasure(file2, m -> m.addValue(ncloc.getKey(), 2.0d)); + db.measures().insertMeasure(file3, m -> m.addValue(ncloc.getKey(), 3.0d)); ComponentTreeWsResponse response = ws.newRequest() .setParam(PARAM_COMPONENT, mainBranch.getKey()) @@ -488,9 +488,9 @@ class ComponentTreeActionIT { db.components().insertComponent(file4); MetricDto ncloc = newMetricDto().setKey("ncloc").setValueType(INT.name()).setDirection(1); dbClient.metricDao().insert(dbSession, ncloc); - db.measures().insertLiveMeasure(file1, ncloc, m -> m.setData((String) null).setValue(1.0d)); - db.measures().insertLiveMeasure(file2, ncloc, m -> m.setData((String) null).setValue(2.0d)); - db.measures().insertLiveMeasure(file3, ncloc, m -> m.setData((String) null).setValue(3.0d)); + db.measures().insertMeasure(file1, m -> m.addValue(ncloc.getKey(), 1.0d)); + db.measures().insertMeasure(file2, m -> m.addValue(ncloc.getKey(), 2.0d)); + db.measures().insertMeasure(file3, m -> m.addValue(ncloc.getKey(), 3.0d)); db.commit(); ComponentTreeWsResponse response = ws.newRequest() @@ -519,9 +519,9 @@ class ComponentTreeActionIT { MetricDto ncloc = newMetricDto().setKey("ncloc").setValueType(INT.name()).setDirection(1); dbClient.metricDao().insert(dbSession, ncloc); db.commit(); - db.measures().insertLiveMeasure(file1, ncloc, m -> m.setValue(1.0d)); - db.measures().insertLiveMeasure(file2, ncloc, m -> m.setValue(2.0d)); - db.measures().insertLiveMeasure(file3, ncloc, m -> m.setValue(3.0d)); + db.measures().insertMeasure(file1, m -> m.addValue(ncloc.getKey(), 1.0d)); + db.measures().insertMeasure(file2, m -> m.addValue(ncloc.getKey(), 2.0d)); + db.measures().insertMeasure(file3, m -> m.addValue(ncloc.getKey(), 3.0d)); ComponentTreeWsResponse response = ws.newRequest() .setParam(PARAM_COMPONENT, mainBranch.getKey()) @@ -546,9 +546,9 @@ class ComponentTreeActionIT { ComponentDto file1 = db.components().insertComponent(newFileDto(mainBranch, null, "file-uuid-1").setKey("file-1-key")); MetricDto ncloc = newMetricDto().setKey("new_ncloc").setValueType(INT.name()).setDirection(1); dbClient.metricDao().insert(dbSession, ncloc); - db.measures().insertLiveMeasure(file1, ncloc, m -> m.setData((String) null).setValue(1.0d)); - db.measures().insertLiveMeasure(file2, ncloc, m -> m.setData((String) null).setValue(2.0d)); - db.measures().insertLiveMeasure(file3, ncloc, m -> m.setData((String) null).setValue(3.0d)); + db.measures().insertMeasure(file1, m -> m.addValue(ncloc.getKey(), 1.0d)); + db.measures().insertMeasure(file2, m -> m.addValue(ncloc.getKey(), 2.0d)); + db.measures().insertMeasure(file3, m -> m.addValue(ncloc.getKey(), 3.0d)); db.commit(); ComponentTreeWsResponse response = ws.newRequest() @@ -596,7 +596,7 @@ class ComponentTreeActionIT { db.components().insertSnapshot(branch); ComponentDto file = db.components().insertComponent(newFileDto(branch, mainBranch.uuid())); MetricDto complexity = db.measures().insertMetric(m -> m.setValueType(INT.name())); - LiveMeasureDto measure = db.measures().insertLiveMeasure(file, complexity, m -> m.setValue(12.0d)); + MeasureDto measure = db.measures().insertMeasure(file, m -> m.addValue(complexity.getKey(), 12.0d)); ComponentTreeWsResponse response = ws.newRequest() .setParam(PARAM_COMPONENT, file.getKey()) @@ -608,7 +608,7 @@ class ComponentTreeActionIT { .containsExactlyInAnyOrder(file.getKey(), branchName); assertThat(response.getBaseComponent().getMeasuresList()) .extracting(Measure::getMetric, m -> parseDouble(m.getValue())) - .containsExactlyInAnyOrder(tuple(complexity.getKey(), measure.getValue())); + .containsExactlyInAnyOrder(tuple(complexity.getKey(), measure.getDouble(complexity.getKey()))); } @Test @@ -659,7 +659,7 @@ class ComponentTreeActionIT { SnapshotDto analysis = db.components().insertSnapshot(branch); ComponentDto file = db.components().insertComponent(newFileDto(branch, mainBranch.uuid())); MetricDto complexity = db.measures().insertMetric(m -> m.setValueType(INT.name())); - LiveMeasureDto measure = db.measures().insertLiveMeasure(file, complexity, m -> m.setValue(12.0d)); + MeasureDto measure = db.measures().insertMeasure(file, m -> m.addValue(complexity.getKey(), 12.0d)); ComponentTreeWsResponse response = ws.newRequest() .setParam(PARAM_COMPONENT, file.getKey()) @@ -671,7 +671,7 @@ class ComponentTreeActionIT { .containsExactlyInAnyOrder(file.getKey(), "pr-123"); assertThat(response.getBaseComponent().getMeasuresList()) .extracting(Measure::getMetric, m -> parseDouble(m.getValue())) - .containsExactlyInAnyOrder(tuple(complexity.getKey(), measure.getValue())); + .containsExactlyInAnyOrder(tuple(complexity.getKey(), measure.getDouble(complexity.getKey()))); } @Test @@ -683,7 +683,7 @@ class ComponentTreeActionIT { MetricDto metricWithoutDomain = db.measures().insertMetric(m -> m .setValueType(Metric.ValueType.INT.name()) .setDomain(null)); - db.measures().insertLiveMeasure(mainBranch, metricWithoutDomain); + db.measures().insertMeasure(mainBranch, m -> m.addValue(metricWithoutDomain.getKey(), 0d)); ComponentTreeWsResponse result = ws.newRequest() .setParam(PARAM_COMPONENT, mainBranch.getKey()) @@ -707,7 +707,7 @@ class ComponentTreeActionIT { SnapshotDto viewAnalysis = db.components().insertSnapshot(view); ComponentDto projectCopy = db.components().insertComponent(newProjectCopy(mainBranch, view)); MetricDto ncloc = insertNclocMetric(); - db.measures().insertLiveMeasure(projectCopy, ncloc, m -> m.setValue(5d)); + db.measures().insertMeasure(projectCopy, m -> m.addValue(ncloc.getKey(), 5d)); ComponentTreeWsResponse result = ws.newRequest() .setParam(PARAM_COMPONENT, view.getKey()) @@ -730,7 +730,7 @@ class ComponentTreeActionIT { ComponentTesting.newSubPortfolio(view, "SUB-VIEW-UUID", "All-Projects").setName("All projects").setCopyComponentUuid(view2.uuid())); db.components().insertSnapshot(view); MetricDto ncloc = insertNclocMetric(); - db.measures().insertLiveMeasure(localView, ncloc, m -> m.setValue(5d)); + db.measures().insertMeasure(localView, m -> m.addValue(ncloc.getKey(), 5d)); ComponentTreeWsResponse result = ws.newRequest() .setParam(PARAM_COMPONENT, view.getKey()) @@ -754,7 +754,7 @@ class ComponentTreeActionIT { ComponentTesting.newSubPortfolio(view, "SUB-VIEW-UUID", "All-Projects").setName("All projects").setCopyComponentUuid(application.uuid())); db.components().insertSnapshot(view); MetricDto ncloc = insertNclocMetric(); - db.measures().insertLiveMeasure(localView, ncloc, m -> m.setValue(5d)); + db.measures().insertMeasure(localView, m -> m.addValue(ncloc.getKey(), 5d)); ComponentTreeWsResponse result = ws.newRequest() .setParam(PARAM_COMPONENT, view.getKey()) @@ -785,8 +785,8 @@ class ComponentTreeActionIT { .setKey(applicationBranch.getKey() + branchName + projectBranch.getKey())); SnapshotDto applicationBranchAnalysis = db.components().insertSnapshot(applicationBranch); - db.measures().insertLiveMeasure(applicationBranch, ncloc, m -> m.setValue(5d)); - db.measures().insertLiveMeasure(techProjectBranch, ncloc, m -> m.setValue(1d)); + db.measures().insertMeasure(applicationBranch, m -> m.addValue(ncloc.getKey(), 5d)); + db.measures().insertMeasure(techProjectBranch, m -> m.addValue(ncloc.getKey(), 1d)); ComponentTreeWsResponse result = ws.newRequest() .setParam(PARAM_COMPONENT, applicationBranch.getKey()) @@ -1176,7 +1176,7 @@ class ComponentTreeActionIT { private void insertMetricAndLiveMeasure(ComponentDto dto, String key, String additionalData) { MetricDto dataMetric = dbClient.metricDao().insert(dbSession, newDataMetricDto(key)); - db.measures().insertLiveMeasure(dto, dataMetric, c -> c.setData(key + additionalData)); + db.measures().insertMeasure(dto, c -> c.addValue(dataMetric.getKey(), key + additionalData)); } diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/SearchActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/SearchActionIT.java index cb373c8bf94..e7b9067beec 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/SearchActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/SearchActionIT.java @@ -76,19 +76,19 @@ public class SearchActionIT { userSession.addProjectPermission(UserRole.USER, project3); MetricDto complexity = db.measures().insertMetric(m -> m.setKey("complexity").setValueType(INT.name())); - db.measures().insertLiveMeasure(project1, complexity, m -> m.setValue(12.0d)); - db.measures().insertLiveMeasure(project2, complexity, m -> m.setValue(35.0d)); - db.measures().insertLiveMeasure(project3, complexity, m -> m.setValue(42.0d)); + db.measures().insertMeasure(project1, m -> m.addValue(complexity.getKey(), 12.0d)); + db.measures().insertMeasure(project2, m -> m.addValue(complexity.getKey(), 35.0d)); + db.measures().insertMeasure(project3, m -> m.addValue(complexity.getKey(), 42.0d)); MetricDto ncloc = db.measures().insertMetric(m -> m.setKey("ncloc").setValueType(INT.name())); - db.measures().insertLiveMeasure(project1, ncloc, m -> m.setValue(114.0d)); - db.measures().insertLiveMeasure(project2, ncloc, m -> m.setValue(217.0d)); - db.measures().insertLiveMeasure(project3, ncloc, m -> m.setValue(1984.0d)); + db.measures().insertMeasure(project1, m -> m.addValue(ncloc.getKey(), 114.0d)); + db.measures().insertMeasure(project2, m -> m.addValue(ncloc.getKey(), 217.0d)); + db.measures().insertMeasure(project3, m -> m.addValue(ncloc.getKey(), 1984.0d)); MetricDto newViolations = db.measures().insertMetric(m -> m.setKey("new_violations").setValueType(INT.name())); - db.measures().insertLiveMeasure(project1, newViolations, m -> m.setValue(25.0d)); - db.measures().insertLiveMeasure(project2, newViolations, m -> m.setValue(25.0d)); - db.measures().insertLiveMeasure(project3, newViolations, m -> m.setValue(255.0d)); + db.measures().insertMeasure(project1, m -> m.addValue(newViolations.getKey(), 25.0d)); + db.measures().insertMeasure(project2, m -> m.addValue(newViolations.getKey(), 25.0d)); + db.measures().insertMeasure(project3, m -> m.addValue(newViolations.getKey(), 255.0d)); List<String> projectKeys = Arrays.asList(project1.getKey(), project2.getKey(), project3.getKey()); @@ -106,7 +106,7 @@ public class SearchActionIT { ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); userSession.addProjectPermission(UserRole.USER, project); MetricDto coverage = db.measures().insertMetric(m -> m.setValueType(FLOAT.name())); - db.measures().insertLiveMeasure(project, coverage, m -> m.setValue(15.5d)); + db.measures().insertMeasure(project, m -> m.addValue(coverage.getKey(), 15.5d)); SearchWsResponse result = call(singletonList(project.getKey()), singletonList(coverage.getKey())); @@ -124,7 +124,7 @@ public class SearchActionIT { MetricDto acceptedIssues = db.measures().insertMetric(m -> m.setValueType(INT.name()) .setKey("accepted_issues") .setShortName("Accepted Issues")); - db.measures().insertLiveMeasure(project, acceptedIssues, m -> m.setValue(10d)); + db.measures().insertMeasure(project, m -> m.addValue(acceptedIssues.getKey(), 10d)); SearchWsResponse result = call(singletonList(project.getKey()), singletonList("wont_fix_issues")); @@ -140,11 +140,11 @@ public class SearchActionIT { ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); userSession.addProjectPermission(UserRole.USER, project); MetricDto matchBestValue = db.measures().insertMetric(m -> m.setValueType(FLOAT.name()).setBestValue(15.5d)); - db.measures().insertLiveMeasure(project, matchBestValue, m -> m.setValue(15.5d)); + db.measures().insertMeasure(project, m -> m.addValue(matchBestValue.getKey(), 15.5d)); MetricDto doesNotMatchBestValue = db.measures().insertMetric(m -> m.setValueType(INT.name()).setBestValue(50d)); - db.measures().insertLiveMeasure(project, doesNotMatchBestValue, m -> m.setValue(40d)); + db.measures().insertMeasure(project, m -> m.addValue(doesNotMatchBestValue.getKey(), 40d)); MetricDto noBestValue = db.measures().insertMetric(m -> m.setValueType(INT.name()).setBestValue(null)); - db.measures().insertLiveMeasure(project, noBestValue, m -> m.setValue(123d)); + db.measures().insertMeasure(project, m -> m.addValue(noBestValue.getKey(), 123d)); SearchWsResponse result = call(singletonList(project.getKey()), asList(matchBestValue.getKey(), doesNotMatchBestValue.getKey(), noBestValue.getKey())); @@ -163,7 +163,7 @@ public class SearchActionIT { ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); userSession.addProjectPermission(UserRole.USER, project); MetricDto coverage = db.measures().insertMetric(m -> m.setKey("new_metric").setValueType(FLOAT.name())); - db.measures().insertLiveMeasure(project, coverage, m -> m.setValue(10d)); + db.measures().insertMeasure(project, m -> m.addValue(coverage.getKey(), 10d)); SearchWsResponse result = call(singletonList(project.getKey()), singletonList(coverage.getKey())); @@ -185,12 +185,12 @@ public class SearchActionIT { userSession.addProjectPermission(UserRole.USER, project1); userSession.addProjectPermission(UserRole.USER, project2); userSession.addProjectPermission(UserRole.USER, project3); - db.measures().insertLiveMeasure(project1, coverage, m -> m.setValue(5.5d)); - db.measures().insertLiveMeasure(project2, coverage, m -> m.setValue(6.5d)); - db.measures().insertLiveMeasure(project3, coverage, m -> m.setValue(7.5d)); - db.measures().insertLiveMeasure(project1, complexity, m -> m.setValue(10d)); - db.measures().insertLiveMeasure(project2, complexity, m -> m.setValue(15d)); - db.measures().insertLiveMeasure(project3, complexity, m -> m.setValue(20d)); + db.measures().insertMeasure(project1, m -> m.addValue(coverage.getKey(), 5.5d)); + db.measures().insertMeasure(project2, m -> m.addValue(coverage.getKey(), 6.5d)); + db.measures().insertMeasure(project3, m -> m.addValue(coverage.getKey(), 7.5d)); + db.measures().insertMeasure(project1, m -> m.addValue(complexity.getKey(), 10d)); + db.measures().insertMeasure(project2, m -> m.addValue(complexity.getKey(), 15d)); + db.measures().insertMeasure(project3, m -> m.addValue(complexity.getKey(), 20d)); SearchWsResponse result = call(asList(project1.getKey(), project2.getKey(), project3.getKey()), asList(coverage.getKey(), complexity.getKey())); @@ -205,7 +205,7 @@ public class SearchActionIT { ComponentDto view = db.components().insertPrivatePortfolio(); userSession.addProjectPermission(UserRole.USER, view); MetricDto coverage = db.measures().insertMetric(m -> m.setValueType(FLOAT.name())); - db.measures().insertLiveMeasure(view, coverage, m -> m.setValue(15.5d)); + db.measures().insertMeasure(view, m -> m.addValue(coverage.getKey(), 15.5d)); SearchWsResponse result = call(singletonList(view.getKey()), singletonList(coverage.getKey())); @@ -221,7 +221,7 @@ public class SearchActionIT { ComponentDto application = db.components().insertPrivateApplication().getMainBranchComponent(); userSession.addProjectPermission(UserRole.USER, application); MetricDto coverage = db.measures().insertMetric(m -> m.setValueType(FLOAT.name())); - db.measures().insertLiveMeasure(application, coverage, m -> m.setValue(15.5d)); + db.measures().insertMeasure(application, m -> m.addValue(coverage.getKey(), 15.5d)); SearchWsResponse result = call(singletonList(application.getKey()), singletonList(coverage.getKey())); @@ -239,7 +239,7 @@ public class SearchActionIT { userSession.addProjectPermission(UserRole.USER, view); userSession.addProjectPermission(UserRole.USER, subView); MetricDto metric = db.measures().insertMetric(m -> m.setValueType(FLOAT.name())); - db.measures().insertLiveMeasure(subView, metric, m -> m.setValue(15.5d)); + db.measures().insertMeasure(subView, m -> m.addValue(metric.getKey(), 15.5d)); SearchWsResponse result = call(singletonList(subView.getKey()), singletonList(metric.getKey())); @@ -255,8 +255,8 @@ public class SearchActionIT { MetricDto metric = db.measures().insertMetric(m -> m.setValueType(FLOAT.name())); ComponentDto project1 = db.components().insertPrivateProject().getMainBranchComponent(); ComponentDto project2 = db.components().insertPrivateProject().getMainBranchComponent(); - db.measures().insertLiveMeasure(project1, metric, m -> m.setValue(15.5d)); - db.measures().insertLiveMeasure(project2, metric, m -> m.setValue(42.0d)); + db.measures().insertMeasure(project1, m -> m.addValue(metric.getKey(), 15.5d)); + db.measures().insertMeasure(project2, m -> m.addValue(metric.getKey(), 42.0d)); Arrays.stream(new ComponentDto[] {project1}).forEach(p -> userSession.addProjectPermission(UserRole.USER, p)); SearchWsResponse result = call(asList(project1.getKey(), project2.getKey()), singletonList(metric.getKey())); @@ -269,7 +269,7 @@ public class SearchActionIT { MetricDto coverage = db.measures().insertMetric(m -> m.setValueType(FLOAT.name())); ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); ComponentDto branch = db.components().insertProjectBranch(project); - db.measures().insertLiveMeasure(branch, coverage, m -> m.setValue(10d)); + db.measures().insertMeasure(branch, m -> m.addValue(coverage.getKey(), 10d)); userSession.addProjectPermission(UserRole.USER, project); SearchWsResponse result = call(singletonList(branch.getKey()), singletonList(coverage.getKey())); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/project/ws/SearchMyProjectsActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/project/ws/SearchMyProjectsActionIT.java index 392a46a4fd3..45066827da9 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/project/ws/SearchMyProjectsActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/project/ws/SearchMyProjectsActionIT.java @@ -52,7 +52,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY; import static org.sonar.db.component.SnapshotTesting.newAnalysis; -import static org.sonar.db.measure.MeasureTesting.newLiveMeasure; +import static org.sonar.db.measure.MeasureTesting.newMeasure; import static org.sonar.db.metric.MetricTesting.newMetricDto; import static org.sonar.db.user.UserTesting.newUserDto; import static org.sonar.test.JsonAssert.assertJson; @@ -90,8 +90,8 @@ public class SearchMyProjectsActionIT { long anotherTime = DateUtils.parseDateTime("2016-06-11T14:25:53+0000").getTime(); SnapshotDto jdk7Snapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(jdk7.getMainBranchDto()).setCreatedAt(oneTime)); SnapshotDto cLangSnapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(cLang.getMainBranchDto()).setCreatedAt(anotherTime)); - dbClient.liveMeasureDao().insert(dbSession, newLiveMeasure(jdk7.getMainBranchDto(), alertStatusMetric).setData(Level.ERROR.name())); - dbClient.liveMeasureDao().insert(dbSession, newLiveMeasure(cLang.getMainBranchDto(), alertStatusMetric).setData(Level.OK.name())); + dbClient.measureDao().insert(dbSession, newMeasure(jdk7.getMainBranchDto(), alertStatusMetric, Level.ERROR.name())); + dbClient.measureDao().insert(dbSession, newMeasure(cLang.getMainBranchDto(), alertStatusMetric, Level.OK.name())); db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, jdk7.getProjectDto()); db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, cLang.getProjectDto()); db.commit(); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualitygate/ws/ProjectStatusActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualitygate/ws/ProjectStatusActionIT.java index 10e2027da73..8e339b42eef 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualitygate/ws/ProjectStatusActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualitygate/ws/ProjectStatusActionIT.java @@ -20,7 +20,6 @@ package org.sonar.server.qualitygate.ws; import java.io.IOException; -import java.nio.charset.StandardCharsets; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.RandomStringUtils; import org.junit.Before; @@ -50,6 +49,7 @@ import org.sonarqube.ws.Qualitygates.ProjectStatusResponse; import org.sonarqube.ws.Qualitygates.ProjectStatusResponse.Status; import static java.lang.String.format; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -60,7 +60,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.sonar.db.component.SnapshotTesting.newAnalysis; -import static org.sonar.db.measure.MeasureTesting.newLiveMeasure; +import static org.sonar.db.measure.MeasureTesting.newMeasure; import static org.sonar.db.measure.MeasureTesting.newProjectMeasureDto; import static org.sonar.db.metric.MetricTesting.newMetricDto; import static org.sonar.server.qualitygate.QualityGateCaycStatus.COMPLIANT; @@ -117,7 +117,7 @@ public class ProjectStatusActionIT { .setPeriodDate(956789123987L)); dbClient.projectMeasureDao().insert(dbSession, newProjectMeasureDto(gateDetailsMetric, mainBranch, snapshot) - .setData(IOUtils.toString(getClass().getResource("ProjectStatusActionIT/measure_data.json"), StandardCharsets.UTF_8))); + .setData(IOUtils.toString(getClass().getResource("ProjectStatusActionIT/measure_data.json"), UTF_8))); dbSession.commit(); String response = ws.newRequest() @@ -144,7 +144,7 @@ public class ProjectStatusActionIT { MetricDto gateDetailsMetric = insertGateDetailMetric(); dbClient.projectMeasureDao().insert(dbSession, newProjectMeasureDto(gateDetailsMetric, mainBranch, pastAnalysis) - .setData(IOUtils.toString(getClass().getResource("ProjectStatusActionIT/measure_data.json")))); + .setData(IOUtils.toString(getClass().getResource("ProjectStatusActionIT/measure_data.json"), UTF_8))); dbClient.projectMeasureDao().insert(dbSession, newProjectMeasureDto(gateDetailsMetric, mainBranch, lastAnalysis) .setData("not_used")); @@ -167,9 +167,8 @@ public class ProjectStatusActionIT { .setPeriodParam("2015-12-07") .setPeriodDate(956789123987L)); MetricDto gateDetailsMetric = insertGateDetailMetric(); - dbClient.liveMeasureDao().insert(dbSession, - newLiveMeasure(mainBranch, gateDetailsMetric) - .setData(IOUtils.toString(getClass().getResource("ProjectStatusActionIT/measure_data.json")))); + dbClient.measureDao().insert(dbSession, + newMeasure(mainBranch, gateDetailsMetric, IOUtils.toString(getClass().getResource("ProjectStatusActionIT/measure_data.json"), UTF_8))); dbSession.commit(); userSession.addProjectPermission(UserRole.USER, projectData.getProjectDto()); @@ -198,7 +197,7 @@ public class ProjectStatusActionIT { MetricDto gateDetailsMetric = insertGateDetailMetric(); dbClient.projectMeasureDao().insert(dbSession, newProjectMeasureDto(gateDetailsMetric, branch, pastAnalysis) - .setData(IOUtils.toString(getClass().getResource("ProjectStatusActionIT/measure_data.json")))); + .setData(IOUtils.toString(getClass().getResource("ProjectStatusActionIT/measure_data.json"), UTF_8))); dbClient.projectMeasureDao().insert(dbSession, newProjectMeasureDto(gateDetailsMetric, branch, lastAnalysis) .setData("not_used")); @@ -221,9 +220,8 @@ public class ProjectStatusActionIT { .setPeriodParam("2015-12-07") .setPeriodDate(956789123987L)); MetricDto gateDetailsMetric = insertGateDetailMetric(); - dbClient.liveMeasureDao().insert(dbSession, - newLiveMeasure(project, gateDetailsMetric) - .setData(IOUtils.toString(getClass().getResource("ProjectStatusActionIT/measure_data.json")))); + dbClient.measureDao().insert(dbSession, + newMeasure(project, gateDetailsMetric, IOUtils.toString(getClass().getResource("ProjectStatusActionIT/measure_data.json"), UTF_8))); dbSession.commit(); userSession.addProjectPermission(UserRole.USER, projectData.getProjectDto()); @@ -246,9 +244,8 @@ public class ProjectStatusActionIT { .setPeriodParam("2015-12-07") .setPeriodDate(956789123987L)); MetricDto gateDetailsMetric = insertGateDetailMetric(); - dbClient.liveMeasureDao().insert(dbSession, - newLiveMeasure(branch, gateDetailsMetric) - .setData(IOUtils.toString(getClass().getResource("ProjectStatusActionIT/measure_data.json")))); + dbClient.measureDao().insert(dbSession, + newMeasure(branch, gateDetailsMetric, IOUtils.toString(getClass().getResource("ProjectStatusActionIT/measure_data.json"), UTF_8))); dbSession.commit(); userSession.addProjectPermission(UserRole.USER, projectData.getProjectDto()); @@ -273,9 +270,8 @@ public class ProjectStatusActionIT { .setPeriodParam("2015-12-07") .setPeriodDate(956789123987L)); MetricDto gateDetailsMetric = insertGateDetailMetric(); - dbClient.liveMeasureDao().insert(dbSession, - newLiveMeasure(pr, gateDetailsMetric) - .setData(IOUtils.toString(getClass().getResource("ProjectStatusActionIT/measure_data.json")))); + dbClient.measureDao().insert(dbSession, + newMeasure(pr, gateDetailsMetric, IOUtils.toString(getClass().getResource("ProjectStatusActionIT/measure_data.json"), UTF_8))); dbSession.commit(); userSession.addProjectPermission(UserRole.USER, projectData.getProjectDto()); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/source/ws/IssueSnippetsActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/source/ws/IssueSnippetsActionIT.java index cc9338561f0..acd17e1e89c 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/source/ws/IssueSnippetsActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/source/ws/IssueSnippetsActionIT.java @@ -32,7 +32,6 @@ import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ProjectData; import org.sonar.db.issue.IssueDto; -import org.sonar.db.metric.MetricDto; import org.sonar.db.protobuf.DbCommons; import org.sonar.db.protobuf.DbFileSources; import org.sonar.db.protobuf.DbIssues; @@ -118,18 +117,12 @@ public class IssueSnippetsActionIT { public void should_add_measures_to_components() { ComponentDto file = insertFile(mainBranchComponent, "file"); - MetricDto lines = db.measures().insertMetric(m -> m.setKey(LINES_KEY)); - db.measures().insertLiveMeasure(file, lines, m -> m.setValue(200d)); - MetricDto duplicatedLines = db.measures().insertMetric(m -> m.setKey(DUPLICATED_LINES_DENSITY_KEY)); - db.measures().insertLiveMeasure(file, duplicatedLines, m -> m.setValue(7.4)); - MetricDto tests = db.measures().insertMetric(m -> m.setKey(TESTS_KEY)); - db.measures().insertLiveMeasure(file, tests, m -> m.setValue(3d)); - MetricDto technicalDebt = db.measures().insertMetric(m -> m.setKey(TECHNICAL_DEBT_KEY)); - db.measures().insertLiveMeasure(file, technicalDebt, m -> m.setValue(182d)); - MetricDto issues = db.measures().insertMetric(m -> m.setKey(VIOLATIONS_KEY)); - db.measures().insertLiveMeasure(file, issues, m -> m.setValue(231d)); - MetricDto coverage = db.measures().insertMetric(m -> m.setKey(COVERAGE_KEY)); - db.measures().insertLiveMeasure(file, coverage, m -> m.setValue(95.4d)); + db.measures().insertMeasure(file, m -> m.addValue(LINES_KEY, 200d)); + db.measures().insertMeasure(file, m -> m.addValue(DUPLICATED_LINES_DENSITY_KEY, 7.4)); + db.measures().insertMeasure(file, m -> m.addValue(TESTS_KEY, 3d)); + db.measures().insertMeasure(file, m -> m.addValue(TECHNICAL_DEBT_KEY, 182d)); + db.measures().insertMeasure(file, m -> m.addValue(VIOLATIONS_KEY, 231d)); + db.measures().insertMeasure(file, m -> m.addValue(COVERAGE_KEY, 95.4d)); DbFileSources.Data fileSources = FileSourceTesting.newFakeData(10).build(); fileSourceTester.insertFileSource(file, 10, dto -> dto.setSourceData(fileSources)); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/ui/ws/ComponentActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/ui/ws/ComponentActionIT.java index aad9cda89aa..41c16adab86 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/ui/ws/ComponentActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/ui/ws/ComponentActionIT.java @@ -87,7 +87,7 @@ import static org.sonar.db.component.ComponentTesting.newFileDto; import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; import static org.sonar.db.component.ComponentTesting.newSubPortfolio; import static org.sonar.db.component.SnapshotTesting.newAnalysis; -import static org.sonar.db.measure.MeasureTesting.newLiveMeasure; +import static org.sonar.db.measure.MeasureTesting.newMeasure; import static org.sonar.db.metric.MetricTesting.newMetricDto; import static org.sonar.db.permission.GlobalPermission.ADMINISTER_QUALITY_GATES; import static org.sonar.db.permission.GlobalPermission.ADMINISTER_QUALITY_PROFILES; @@ -844,9 +844,7 @@ public class ComponentActionIT { private void addQualityProfiles(ComponentDto project, QualityProfile... qps) { MetricDto metric = newMetricDto().setKey(QUALITY_PROFILES_KEY); dbClient.metricDao().insert(db.getSession(), metric); - dbClient.liveMeasureDao().insert(db.getSession(), - newLiveMeasure(project, metric) - .setData(qualityProfilesToJson(qps))); + dbClient.measureDao().insert(db.getSession(), newMeasure(project, metric, qualityProfilesToJson(qps))); db.commit(); } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/MeasureAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/MeasureAction.java index bf604a531db..e9f3b337c94 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/MeasureAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/MeasureAction.java @@ -31,7 +31,7 @@ import org.sonar.api.server.ws.WebService.NewAction; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.BranchDto; -import org.sonar.db.measure.LiveMeasureDto; +import org.sonar.db.measure.MeasureDto; import org.sonar.db.metric.MetricDto; import org.sonar.server.badge.ws.SvgGenerator.Color; import org.sonar.server.measure.Rating; @@ -62,7 +62,6 @@ import static org.sonar.server.measure.Rating.B; import static org.sonar.server.measure.Rating.C; import static org.sonar.server.measure.Rating.D; import static org.sonar.server.measure.Rating.E; -import static org.sonar.server.measure.Rating.valueOf; public class MeasureAction extends AbstractProjectBadgesWsAction { @@ -114,7 +113,7 @@ public class MeasureAction extends AbstractProjectBadgesWsAction { .setDescription("Generate badge for project's measure as an SVG.<br/>" + "Requires 'Browse' permission on the specified project.") .setSince("7.1") - .setChangelog(new Change("10.4", String.format("The following metric keys are now deprecated: %s", String.join(", ", + .setChangelog(new Change("10.4", format("The following metric keys are now deprecated: %s", String.join(", ", DEPRECATED_METRIC_KEYS)))) .setResponseExample(Resources.getResource(getClass(), "measure-example.svg")); support.addProjectAndBranchParams(action); @@ -131,27 +130,27 @@ public class MeasureAction extends AbstractProjectBadgesWsAction { BranchDto branch = support.getBranch(dbSession, request); MetricDto metric = dbClient.metricDao().selectByKey(dbSession, metricKey); checkState(metric != null && metric.isEnabled(), "Metric '%s' hasn't been found", metricKey); - LiveMeasureDto measure = getMeasure(dbSession, branch, metricKey); + MeasureDto measure = getMeasure(dbSession, branch); return generateSvg(metric, measure); } } - private LiveMeasureDto getMeasure(DbSession dbSession, BranchDto branch, String metricKey) { - return dbClient.liveMeasureDao().selectMeasure(dbSession, branch.getUuid(), metricKey) + private MeasureDto getMeasure(DbSession dbSession, BranchDto branch) { + return dbClient.measureDao().selectByComponentUuid(dbSession, branch.getUuid()) .orElseThrow(() -> new ProjectBadgesException("Measure has not been found")); } - private String generateSvg(MetricDto metric, LiveMeasureDto measure) { + private String generateSvg(MetricDto metric, MeasureDto measure) { String metricType = metric.getValueType(); switch (ValueType.valueOf(metricType)) { case INT: - return generateBadge(metric, formatNumeric(getNonNullValue(measure, LiveMeasureDto::getValue).longValue()), Color.DEFAULT); + return generateBadge(metric, formatNumeric(getNonNullValue(measure, m -> m.getLong(metric.getKey()))), Color.DEFAULT); case PERCENT: - return generateBadge(metric, formatPercent(getNonNullValue(measure, LiveMeasureDto::getValue)), Color.DEFAULT); + return generateBadge(metric, formatPercent(getNonNullValue(measure, m -> m.getDouble(metric.getKey()))), Color.DEFAULT); case LEVEL: return generateQualityGate(metric, measure); case WORK_DUR: - return generateBadge(metric, formatDuration(getNonNullValue(measure, LiveMeasureDto::getValue).longValue()), Color.DEFAULT); + return generateBadge(metric, formatDuration(getNonNullValue(measure, m -> m.getLong(metric.getKey()))), Color.DEFAULT); case RATING: return generateRating(metric, measure); default: @@ -159,13 +158,13 @@ public class MeasureAction extends AbstractProjectBadgesWsAction { } } - private String generateQualityGate(MetricDto metric, LiveMeasureDto measure) { - Level qualityGate = Level.valueOf(getNonNullValue(measure, LiveMeasureDto::getTextValue)); + private String generateQualityGate(MetricDto metric, MeasureDto measure) { + Level qualityGate = Level.valueOf(getNonNullValue(measure, m -> m.getString(metric.getKey()))); return generateBadge(metric, QUALITY_GATE_MESSAGE_BY_STATUS.get(qualityGate), COLOR_BY_QUALITY_GATE_STATUS.get(qualityGate)); } - private String generateRating(MetricDto metric, LiveMeasureDto measure) { - Rating rating = valueOf(getNonNullValue(measure, LiveMeasureDto::getValue).intValue()); + private String generateRating(MetricDto metric, MeasureDto measure) { + Rating rating = Rating.valueOf(getNonNullValue(measure, m -> m.getInt(metric.getKey())).intValue()); return generateBadge(metric, rating.name(), COLOR_BY_RATING.get(rating)); } @@ -173,7 +172,7 @@ public class MeasureAction extends AbstractProjectBadgesWsAction { return svgGenerator.generateBadge(METRIC_NAME_BY_KEY.get(metric.getKey()), value, color); } - private static <P> P getNonNullValue(LiveMeasureDto measure, Function<LiveMeasureDto, P> function) { + private static <P> P getNonNullValue(MeasureDto measure, Function<MeasureDto, P> function) { P value = function.apply(measure); checkState(value != null, "Measure has not been found"); return value; diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/QualityGateAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/QualityGateAction.java index a4d03563852..09000449f9c 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/QualityGateAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/QualityGateAction.java @@ -27,7 +27,6 @@ import org.sonar.api.server.ws.WebService.NewAction; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.BranchDto; -import org.sonar.db.measure.LiveMeasureDto; import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY; @@ -61,8 +60,8 @@ public class QualityGateAction extends AbstractProjectBadgesWsAction { } private Level getQualityGate(DbSession dbSession, BranchDto branch) { - return Level.valueOf(dbClient.liveMeasureDao().selectMeasure(dbSession, branch.getUuid(), ALERT_STATUS_KEY) - .map(LiveMeasureDto::getTextValue) + return Level.valueOf(dbClient.measureDao().selectByComponentUuid(dbSession, branch.getUuid()) + .map(m -> m.getString(ALERT_STATUS_KEY)) .orElseThrow(() -> new ProjectBadgesException("Quality gate has not been found"))); } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/branch/ws/ListAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/branch/ws/ListAction.java index d321345e398..662ddf83663 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/branch/ws/ListAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/branch/ws/ListAction.java @@ -35,7 +35,7 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.BranchDto; import org.sonar.db.component.SnapshotDto; -import org.sonar.db.measure.LiveMeasureDto; +import org.sonar.db.measure.MeasureDto; import org.sonar.db.project.ProjectDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.user.UserSession; @@ -94,9 +94,9 @@ public class ListAction implements BranchWsAction { .toList(); List<String> branchUuids = branches.stream().map(BranchDto::getUuid).toList(); - Map<String, LiveMeasureDto> qualityGateMeasuresByComponentUuids = dbClient.liveMeasureDao() + Map<String, MeasureDto> qualityGateMeasuresByComponentUuids = dbClient.measureDao() .selectByComponentUuidsAndMetricKeys(dbSession, branchUuids, singletonList(ALERT_STATUS_KEY)).stream() - .collect(Collectors.toMap(LiveMeasureDto::getComponentUuid, Function.identity())); + .collect(Collectors.toMap(MeasureDto::getComponentUuid, Function.identity())); Map<String, String> analysisDateByBranchUuid = dbClient.snapshotDao() .selectLastAnalysesByRootComponentUuids(dbSession, branchUuids).stream() .collect(Collectors.toMap(SnapshotDto::getRootComponentUuid, s -> formatDateTime(s.getCreatedAt()))); @@ -109,7 +109,7 @@ public class ListAction implements BranchWsAction { } private static void addBranch(ProjectBranches.ListWsResponse.Builder response, BranchDto branch, - @Nullable LiveMeasureDto qualityGateMeasure, @Nullable String analysisDate) { + @Nullable MeasureDto qualityGateMeasure, @Nullable String analysisDate) { ProjectBranches.Branch.Builder builder = toBranchBuilder(branch); setBranchStatus(builder, qualityGateMeasure); if (analysisDate != null) { @@ -129,10 +129,10 @@ public class ListAction implements BranchWsAction { return builder; } - private static void setBranchStatus(ProjectBranches.Branch.Builder builder, @Nullable LiveMeasureDto qualityGateMeasure) { + private static void setBranchStatus(ProjectBranches.Branch.Builder builder, @Nullable MeasureDto qualityGateMeasure) { ProjectBranches.Status.Builder statusBuilder = ProjectBranches.Status.newBuilder(); if (qualityGateMeasure != null) { - ofNullable(qualityGateMeasure.getDataAsString()).ifPresent(statusBuilder::setQualityGateStatus); + ofNullable(qualityGateMeasure.getString(ALERT_STATUS_KEY)).ifPresent(statusBuilder::setQualityGateStatus); } builder.setStatus(statusBuilder); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentCleanerService.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentCleanerService.java index 9cb298b88e4..7b407c46931 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentCleanerService.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentCleanerService.java @@ -61,7 +61,7 @@ public class ComponentCleanerService { } private void updateProjectNcloc(DbSession dbSession, String projectUuid) { - long maxncloc = dbClient.liveMeasureDao().findNclocOfBiggestBranchForProject(dbSession, projectUuid); + long maxncloc = dbClient.measureDao().findNclocOfBiggestBranchForProject(dbSession, projectUuid); dbClient.projectDao().updateNcloc(dbSession, projectUuid, maxncloc); } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/ComponentViewerJsonWriter.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/ComponentViewerJsonWriter.java index 7c40b7616b6..9d975116fa7 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/ComponentViewerJsonWriter.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/ComponentViewerJsonWriter.java @@ -19,10 +19,7 @@ */ package org.sonar.server.component.ws; -import com.google.common.collect.Maps; -import java.util.Collections; import java.util.List; -import java.util.Map; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.apache.commons.lang3.BooleanUtils; @@ -32,30 +29,18 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDto; import org.sonar.db.entity.EntityDto; -import org.sonar.db.measure.LiveMeasureDto; -import org.sonar.db.metric.MetricDto; +import org.sonar.db.measure.MeasureDto; import org.sonar.db.property.PropertyDto; import org.sonar.db.property.PropertyQuery; import org.sonar.server.user.UserSession; import static org.sonar.api.measures.CoreMetrics.COVERAGE; -import static org.sonar.api.measures.CoreMetrics.COVERAGE_KEY; import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES_DENSITY; -import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES_DENSITY_KEY; import static org.sonar.api.measures.CoreMetrics.LINES; -import static org.sonar.api.measures.CoreMetrics.LINES_KEY; import static org.sonar.api.measures.CoreMetrics.TESTS; -import static org.sonar.api.measures.CoreMetrics.TESTS_KEY; import static org.sonar.api.measures.CoreMetrics.VIOLATIONS; -import static org.sonar.api.measures.CoreMetrics.VIOLATIONS_KEY; public class ComponentViewerJsonWriter { - private static final List<String> METRIC_KEYS = List.of( - LINES_KEY, - VIOLATIONS_KEY, - COVERAGE_KEY, - DUPLICATED_LINES_DENSITY_KEY, - TESTS_KEY); private final DbClient dbClient; @@ -96,36 +81,28 @@ public class ComponentViewerJsonWriter { } public void writeMeasures(JsonWriter json, ComponentDto component, DbSession session) { - Map<String, LiveMeasureDto> measuresByMetricKey = loadMeasuresGroupedByMetricKey(component, session); + MeasureDto measureDto = loadMeasures(component, session); json.name("measures").beginObject(); - json.prop("lines", formatMeasure(measuresByMetricKey, LINES)); - json.prop("coverage", formatMeasure(measuresByMetricKey, COVERAGE)); - json.prop("duplicationDensity", formatMeasure(measuresByMetricKey, DUPLICATED_LINES_DENSITY)); - json.prop("issues", formatMeasure(measuresByMetricKey, VIOLATIONS)); - json.prop("tests", formatMeasure(measuresByMetricKey, TESTS)); + json.prop("lines", formatMeasure(measureDto, LINES)); + json.prop("coverage", formatMeasure(measureDto, COVERAGE)); + json.prop("duplicationDensity", formatMeasure(measureDto, DUPLICATED_LINES_DENSITY)); + json.prop("issues", formatMeasure(measureDto, VIOLATIONS)); + json.prop("tests", formatMeasure(measureDto, TESTS)); json.endObject(); } - private Map<String, LiveMeasureDto> loadMeasuresGroupedByMetricKey(ComponentDto component, DbSession dbSession) { - List<MetricDto> metrics = dbClient.metricDao().selectByKeys(dbSession, METRIC_KEYS); - Map<String, MetricDto> metricsByUuid = Maps.uniqueIndex(metrics, MetricDto::getUuid); - List<LiveMeasureDto> measures = dbClient.liveMeasureDao() - .selectByComponentUuidsAndMetricUuids(dbSession, Collections.singletonList(component.uuid()), metricsByUuid.keySet()); - return Maps.uniqueIndex(measures, m -> metricsByUuid.get(m.getMetricUuid()).getKey()); - } - @CheckForNull - private static String formatMeasure(Map<String, LiveMeasureDto> measuresByMetricKey, Metric metric) { - LiveMeasureDto measure = measuresByMetricKey.get(metric.getKey()); - return formatMeasure(measure, metric); + private MeasureDto loadMeasures(ComponentDto component, DbSession dbSession) { + return dbClient.measureDao().selectByComponentUuid(dbSession, component.uuid()).orElse(null); } - private static String formatMeasure(@Nullable LiveMeasureDto measure, Metric metric) { - if (measure == null) { + @CheckForNull + private static String formatMeasure(@Nullable MeasureDto measureDto, Metric<?> metric) { + if (measureDto == null) { return null; } - Double value = getDoubleValue(measure, metric); + Double value = getDoubleValue(measureDto, metric); if (value != null) { return Double.toString(value); } @@ -133,12 +110,11 @@ public class ComponentViewerJsonWriter { } @CheckForNull - private static Double getDoubleValue(LiveMeasureDto measure, Metric metric) { - Double value = measure.getValue(); + private static Double getDoubleValue(MeasureDto measureDto, Metric<?> metric) { + Double value = measureDto.getDouble(metric.getKey()); if (BooleanUtils.isTrue(metric.isOptimizedBestValue()) && value == null) { value = metric.getBestValue(); } return value; } - } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java index 374d3e96dff..149524ee287 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java @@ -338,10 +338,10 @@ public class SearchProjectsAction implements ComponentsWsAction { private Map<String, Long> getApplicationsLeakPeriod(DbSession dbSession, SearchProjectsRequest request, Set<String> qualifiers, Collection<String> mainBranchUuids) { if (qualifiers.contains(Qualifiers.APP) && request.getAdditionalFields().contains(LEAK_PERIOD_DATE)) { - return dbClient.liveMeasureDao().selectByComponentUuidsAndMetricKeys(dbSession, mainBranchUuids, Collections.singleton(METRIC_LEAK_PROJECTS_KEY)) + return dbClient.measureDao().selectByComponentUuidsAndMetricKeys(dbSession, mainBranchUuids, Collections.singleton(METRIC_LEAK_PROJECTS_KEY)) .stream() - .filter(lm -> !Objects.isNull(lm.getDataAsString())) - .map(lm -> Maps.immutableEntry(lm.getComponentUuid(), ApplicationLeakProjects.parse(lm.getDataAsString()).getOldestLeak())) + .filter(m -> !Objects.isNull(m.getString(METRIC_LEAK_PROJECTS_KEY))) + .map(m -> Maps.immutableEntry(m.getComponentUuid(), ApplicationLeakProjects.parse(m.getString(METRIC_LEAK_PROJECTS_KEY)).getOldestLeak())) .filter(entry -> entry.getValue().isPresent()) .collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().get().getLeak())); } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/duplication/ws/ShowAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/duplication/ws/ShowAction.java index d8bbc4faf95..cd04dcaf603 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/duplication/ws/ShowAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/duplication/ws/ShowAction.java @@ -32,7 +32,6 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.BranchDto; import org.sonar.db.component.ComponentDto; -import org.sonar.db.measure.LiveMeasureDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.user.UserSession; @@ -128,8 +127,8 @@ public class ShowAction implements DuplicationsWsAction { @CheckForNull private String findDataFromComponent(DbSession dbSession, ComponentDto component) { - return dbClient.liveMeasureDao().selectMeasure(dbSession, component.uuid(), CoreMetrics.DUPLICATIONS_DATA_KEY) - .map(LiveMeasureDto::getDataAsString) + return dbClient.measureDao().selectByComponentUuid(dbSession, component.uuid()) + .map(m -> m.getString(CoreMetrics.DUPLICATIONS_DATA_KEY)) .orElse(null); } } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/NewCodePeriodResolver.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/NewCodePeriodResolver.java index 06aba46e86b..d56ef16a8e4 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/NewCodePeriodResolver.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/NewCodePeriodResolver.java @@ -66,7 +66,9 @@ public class NewCodePeriodResolver { } private boolean isLastAnalysisFromSonarQube94Onwards(DbSession dbSession, String componentUuid) { - return dbClient.liveMeasureDao().selectMeasure(dbSession, componentUuid, ANALYSIS_FROM_SONARQUBE_9_4_KEY).isPresent(); + return dbClient.measureDao().selectByComponentUuid(dbSession, componentUuid) + .filter(m -> m.getMetricValues().containsKey(ANALYSIS_FROM_SONARQUBE_9_4_KEY)) + .isPresent(); } private static boolean isLastAnalysisUsingReferenceBranch(SnapshotDto snapshot) { diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/LiveMeasureComputerImpl.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/LiveMeasureComputerImpl.java index 8d6d2f693f9..1b997b5f331 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/LiveMeasureComputerImpl.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/LiveMeasureComputerImpl.java @@ -142,7 +142,7 @@ public class LiveMeasureComputerImpl implements LiveMeasureComputer { @CheckForNull private Metric.Level loadPreviousStatus(DbSession dbSession, ComponentDto branchComponent) { - return dbClient.measureDao().selectMeasure(dbSession, branchComponent.uuid()) + return dbClient.measureDao().selectByComponentUuid(dbSession, branchComponent.uuid()) .map(m -> m.getString(ALERT_STATUS_KEY)) .map(m -> { try { diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentAction.java index c5b775936c5..e05fee40672 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentAction.java @@ -20,12 +20,9 @@ package org.sonar.server.measure.ws; import com.google.common.collect.ImmutableSortedSet; -import com.google.common.collect.Maps; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -42,7 +39,7 @@ import org.sonar.db.DbSession; import org.sonar.db.component.BranchDto; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.SnapshotDto; -import org.sonar.db.measure.LiveMeasureDto; +import org.sonar.db.measure.MeasureDto; import org.sonar.db.metric.MetricDto; import org.sonar.db.metric.MetricDtoFunctions; import org.sonar.server.component.ComponentFinder; @@ -53,7 +50,6 @@ import org.sonarqube.ws.Measures.ComponentWsResponse; import static java.lang.String.format; import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static org.sonar.db.metric.RemovedMetricConverter.withRemovedMetricAlias; import static org.sonar.server.component.ws.MeasuresWsParameters.ACTION_COMPONENT; @@ -161,11 +157,10 @@ public class ComponentAction implements MeasuresWsAction { SnapshotDto analysis = dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(dbSession, component.branchUuid()).orElse(null); List<MetricDto> metrics = searchMetrics(dbSession, new HashSet<>(withRemovedMetricAlias(request.getMetricKeys()))); - List<LiveMeasureDto> measures = searchMeasures(dbSession, component, metrics); - Map<MetricDto, LiveMeasureDto> measuresByMetric = getMeasuresByMetric(measures, metrics); + MeasureDto measureDto = searchMeasures(dbSession, component, metrics); Measures.Period period = snapshotToWsPeriods(analysis).orElse(null); - return buildResponse(dbSession, request, component, measuresByMetric, metrics, period, request.getMetricKeys()); + return buildResponse(dbSession, request, component, measureDto, metrics, period, request.getMetricKeys()); } } @@ -180,21 +175,11 @@ public class ComponentAction implements MeasuresWsAction { return metrics; } - private List<LiveMeasureDto> searchMeasures(DbSession dbSession, ComponentDto component, Collection<MetricDto> metrics) { - Set<String> metricUuids = metrics.stream().map(MetricDto::getUuid).collect(Collectors.toSet()); - List<LiveMeasureDto> measures = dbClient.liveMeasureDao().selectByComponentUuidsAndMetricUuids(dbSession, singletonList(component.uuid()), metricUuids); - addBestValuesToMeasures(measures, component, metrics); - return measures; - } - - private static Map<MetricDto, LiveMeasureDto> getMeasuresByMetric(List<LiveMeasureDto> measures, Collection<MetricDto> metrics) { - Map<String, MetricDto> metricsByUuid = Maps.uniqueIndex(metrics, MetricDto::getUuid); - Map<MetricDto, LiveMeasureDto> measuresByMetric = new HashMap<>(); - for (LiveMeasureDto measure : measures) { - MetricDto metric = metricsByUuid.get(measure.getMetricUuid()); - measuresByMetric.put(metric, measure); - } - return measuresByMetric; + @CheckForNull + private MeasureDto searchMeasures(DbSession dbSession, ComponentDto component, Collection<MetricDto> metrics) { + MeasureDto measureDto = dbClient.measureDao().selectByComponentUuid(dbSession, component.uuid()).orElse(null); + addBestValuesToMeasures(measureDto, component, metrics); + return measureDto; } /** @@ -204,22 +189,19 @@ public class ComponentAction implements MeasuresWsAction { * <li>metric is optimized for best value</li> * </ul> */ - private static void addBestValuesToMeasures(List<LiveMeasureDto> measures, ComponentDto component, Collection<MetricDto> metrics) { - if (!QUALIFIERS_ELIGIBLE_FOR_BEST_VALUE.contains(component.qualifier())) { + private static void addBestValuesToMeasures(@Nullable MeasureDto measureDto, ComponentDto component, Collection<MetricDto> metrics) { + if (measureDto == null || !QUALIFIERS_ELIGIBLE_FOR_BEST_VALUE.contains(component.qualifier())) { return; } - List<MetricDtoWithBestValue> metricWithBestValueList = metrics.stream() + metrics.stream() .filter(MetricDtoFunctions.isOptimizedForBestValue()) - .map(MetricDtoWithBestValue::new) - .toList(); - Map<String, LiveMeasureDto> measuresByMetricUuid = Maps.uniqueIndex(measures, LiveMeasureDto::getMetricUuid); - - for (MetricDtoWithBestValue metricWithBestValue : metricWithBestValueList) { - if (measuresByMetricUuid.get(metricWithBestValue.getMetric().getUuid()) == null) { - measures.add(metricWithBestValue.getBestValue()); - } - } + .forEach(metricWithBestValue -> { + String metricKey = metricWithBestValue.getKey(); + if (!measureDto.getMetricValues().containsKey(metricKey)) { + measureDto.addValue(metricKey, metricWithBestValue.getBestValue()); + } + }); } private ComponentDto loadComponent(DbSession dbSession, ComponentRequest request, @Nullable String branch, @Nullable String pullRequest) { @@ -243,8 +225,7 @@ public class ComponentAction implements MeasuresWsAction { } private ComponentWsResponse buildResponse(DbSession dbSession, ComponentRequest request, ComponentDto component, - Map<MetricDto, LiveMeasureDto> measuresByMetric, Collection<MetricDto> metrics, @Nullable Measures.Period period, - Collection<String> requestedMetrics) { + @Nullable MeasureDto measureDto, Collection<MetricDto> metrics, @Nullable Measures.Period period, Collection<String> requestedMetrics) { ComponentWsResponse.Builder response = ComponentWsResponse.newBuilder(); @@ -252,12 +233,12 @@ public class ComponentAction implements MeasuresWsAction { if (reference != null) { BranchDto refBranch = reference.getRefBranch(); ComponentDto refComponent = reference.getComponent(); - response.setComponent(componentDtoToWsComponent(component, measuresByMetric, singletonMap(refComponent.uuid(), refComponent), - refBranch.isMain() ? null : refBranch.getBranchKey(), null, requestedMetrics)); + response.setComponent(componentDtoToWsComponent(component, measureDto, singletonMap(refComponent.uuid(), refComponent), + refBranch.isMain() ? null : refBranch.getBranchKey(), null, metrics, requestedMetrics)); } else { boolean isMainBranch = dbClient.branchDao().selectByUuid(dbSession, component.branchUuid()).map(BranchDto::isMain).orElse(true); - response.setComponent(componentDtoToWsComponent(component, measuresByMetric, emptyMap(), isMainBranch ? null : request.getBranch(), - request.getPullRequest(), requestedMetrics)); + response.setComponent(componentDtoToWsComponent(component, measureDto, emptyMap(), isMainBranch ? null : request.getBranch(), + request.getPullRequest(), metrics, requestedMetrics)); } setAdditionalFields(request, metrics, period, response, requestedMetrics); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentDtoToWsComponent.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentDtoToWsComponent.java index e2170b08c16..1b806b9100e 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentDtoToWsComponent.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentDtoToWsComponent.java @@ -21,9 +21,11 @@ package org.sonar.server.measure.ws; import java.util.Collection; import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; import javax.annotation.Nullable; import org.sonar.db.component.ComponentDto; -import org.sonar.db.measure.LiveMeasureDto; +import org.sonar.db.measure.MeasureDto; import org.sonar.db.metric.MetricDto; import org.sonarqube.ws.Measures; import org.sonarqube.ws.Measures.Component; @@ -36,9 +38,9 @@ class ComponentDtoToWsComponent { // static methods only } - static Component.Builder componentDtoToWsComponent(ComponentDto component, Map<MetricDto, LiveMeasureDto> measuresByMetric, - Map<String, ComponentDto> referenceComponentsByUuid, @Nullable String branch, - @Nullable String pullRequest, Collection<String> requestedMetrics) { + static Component.Builder componentDtoToWsComponent(ComponentDto component, @Nullable MeasureDto measureDto, + Map<String, ComponentDto> referenceComponentsByUuid, @Nullable String branch, @Nullable String pullRequest, + Collection<MetricDto> metrics, Collection<String> requestedMetrics) { Component.Builder wsComponent = componentDtoToWsComponent(component, branch, pullRequest); ComponentDto referenceComponent = referenceComponentsByUuid.get(component.getCopyComponentUuid()); @@ -46,11 +48,16 @@ class ComponentDtoToWsComponent { wsComponent.setRefKey(referenceComponent.getKey()); } - Measures.Measure.Builder measureBuilder = Measures.Measure.newBuilder(); - for (Map.Entry<MetricDto, LiveMeasureDto> entry : measuresByMetric.entrySet()) { - MeasureDtoToWsMeasure.updateMeasureBuilder(measureBuilder, entry.getKey(), entry.getValue()); - addMeasureIncludingRenamedMetric(requestedMetrics, wsComponent, measureBuilder); - measureBuilder.clear(); + if (measureDto != null) { + Measures.Measure.Builder measureBuilder = Measures.Measure.newBuilder(); + Map<String, MetricDto> metricsByKey = metrics.stream().collect(Collectors.toMap(MetricDto::getKey, Function.identity())); + metricsByKey.keySet().stream() + .filter(metricKey -> measureDto.getMetricValues().containsKey(metricKey)) + .forEach(metricKey -> { + MeasureDtoToWsMeasure.updateMeasureBuilder(measureBuilder, metricsByKey.get(metricKey), measureDto); + addMeasureIncludingRenamedMetric(requestedMetrics, wsComponent, measureBuilder); + measureBuilder.clear(); + }); } return wsComponent; diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java index 5ee3d95b34a..235ac6088a3 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java @@ -61,7 +61,7 @@ import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTreeQuery; import org.sonar.db.component.ComponentTreeQuery.Strategy; import org.sonar.db.component.SnapshotDto; -import org.sonar.db.measure.LiveMeasureDto; +import org.sonar.db.measure.MeasureDto; import org.sonar.db.measure.MeasureTreeQuery; import org.sonar.db.metric.MetricDto; import org.sonar.db.metric.MetricDtoFunctions; @@ -74,8 +74,8 @@ import org.sonarqube.ws.client.component.ComponentsWsParameters; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; -import static java.lang.String.*; import static java.lang.String.format; +import static java.lang.String.join; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static java.util.Optional.ofNullable; @@ -559,22 +559,26 @@ public class ComponentTreeAction implements MeasuresWsAction { ComponentDto baseComponent, ComponentTreeQuery componentTreeQuery, List<ComponentDto> components, List<MetricDto> metrics) { - Map<String, MetricDto> metricsByUuid = Maps.uniqueIndex(metrics, MetricDto::getUuid); + Map<String, MetricDto> metricsByKeys = Maps.uniqueIndex(metrics, MetricDto::getKey); MeasureTreeQuery measureQuery = MeasureTreeQuery.builder() .setStrategy(MeasureTreeQuery.Strategy.valueOf(componentTreeQuery.getStrategy().name())) .setNameOrKeyQuery(componentTreeQuery.getNameOrKeyQuery()) .setQualifiers(componentTreeQuery.getQualifiers()) - .setMetricUuids(new ArrayList<>(metricsByUuid.keySet())) .build(); Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric = HashBasedTable.create(components.size(), metrics.size()); - dbClient.liveMeasureDao().selectTreeByQuery(dbSession, baseComponent, measureQuery, result -> { - LiveMeasureDto measureDto = result.getResultObject(); - measuresByComponentUuidAndMetric.put( - measureDto.getComponentUuid(), - metricsByUuid.get(measureDto.getMetricUuid()), - ComponentTreeData.Measure.createFromMeasureDto(measureDto)); + dbClient.measureDao().selectTreeByQuery(dbSession, baseComponent, measureQuery, result -> { + MeasureDto measureDto = result.getResultObject(); + measureDto.getMetricValues().forEach((metricKey, value) -> { + MetricDto metric = metricsByKeys.get(metricKey); + if (metric != null) { + measuresByComponentUuidAndMetric.put( + measureDto.getComponentUuid(), + metric, + ComponentTreeData.Measure.createFromMetricValue(metric, value)); + } + }); }); addBestValuesToMeasures(measuresByComponentUuidAndMetric, components, metrics); @@ -605,7 +609,7 @@ public class ComponentTreeAction implements MeasuresWsAction { for (MetricDtoWithBestValue metricWithBestValue : metricDtosWithBestValueMeasure) { if (measuresByComponentUuidAndMetric.get(component.uuid(), metricWithBestValue.getMetric()) == null) { measuresByComponentUuidAndMetric.put(component.uuid(), metricWithBestValue.getMetric(), - ComponentTreeData.Measure.createFromMeasureDto(metricWithBestValue.getBestValue())); + ComponentTreeData.Measure.createFromMetricValue(metricWithBestValue.getMetric(), metricWithBestValue.getBestValue())); } } }); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java index 51460ccb989..a5d98135e54 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java @@ -24,15 +24,17 @@ import java.util.List; import java.util.Map; import javax.annotation.CheckForNull; import javax.annotation.Nullable; +import org.sonar.api.measures.Metric; import org.sonar.db.component.BranchDto; import org.sonar.db.component.ComponentDto; -import org.sonar.db.measure.LiveMeasureDto; import org.sonar.db.metric.MetricDto; import org.sonarqube.ws.Measures; import static java.lang.Double.NaN; import static java.lang.Double.isNaN; import static java.util.Objects.requireNonNull; +import static org.sonar.server.measure.ws.ComponentTreeSort.NUMERIC_VALUE_TYPES; +import static org.sonar.server.measure.ws.ComponentTreeSort.TEXTUAL_VALUE_TYPES; class ComponentTreeData { private final ComponentDto baseComponent; @@ -177,10 +179,6 @@ class ComponentTreeData { this.value = toPrimitive(value); } - private Measure(LiveMeasureDto measureDto) { - this(measureDto.getDataAsString(), measureDto.getValue()); - } - public double getValue() { return value; } @@ -194,8 +192,20 @@ class ComponentTreeData { return data; } - static Measure createFromMeasureDto(LiveMeasureDto measureDto) { - return new Measure(measureDto); + static Measure createFromMetricValue(MetricDto metric, @Nullable Object value) { + if (value == null) { + return null; + } + + Metric.ValueType metricValueType = Metric.ValueType.valueOf(metric.getValueType()); + if (NUMERIC_VALUE_TYPES.contains(metricValueType)) { + return new Measure(null, (double) value); + } else if (TEXTUAL_VALUE_TYPES.contains(metricValueType) + || List.of(Metric.ValueType.DATA, Metric.ValueType.LEVEL).contains(metricValueType)) { + return new Measure(value.toString(), null); + } else { + return null; + } } private static double toPrimitive(@Nullable Double value) { diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeSort.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeSort.java index a1b04613433..7969675fb6c 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeSort.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeSort.java @@ -58,8 +58,8 @@ import static org.sonar.server.measure.ws.ComponentTreeAction.QUALIFIER_SORT; public class ComponentTreeSort { - private static final Set<ValueType> NUMERIC_VALUE_TYPES = EnumSet.of(BOOL, FLOAT, INT, MILLISEC, WORK_DUR, PERCENT, RATING); - private static final Set<ValueType> TEXTUAL_VALUE_TYPES = EnumSet.of(STRING); + static final Set<ValueType> NUMERIC_VALUE_TYPES = EnumSet.of(BOOL, FLOAT, INT, MILLISEC, WORK_DUR, PERCENT, RATING); + static final Set<ValueType> TEXTUAL_VALUE_TYPES = EnumSet.of(STRING); private ComponentTreeSort() { // static method only diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java index 4651174acb9..76541f0f628 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java @@ -21,6 +21,7 @@ package org.sonar.server.measure.ws; import javax.annotation.Nullable; import org.sonar.db.measure.LiveMeasureDto; +import org.sonar.db.measure.MeasureDto; import org.sonar.db.measure.ProjectMeasureDto; import org.sonar.db.metric.MetricDto; import org.sonarqube.ws.Measures; @@ -48,6 +49,24 @@ class MeasureDtoToWsMeasure { updateMeasureBuilder(measureBuilder, metricDto, value, measureDto.getDataAsString(), onNewCode); } + static void updateMeasureBuilder(Measure.Builder measureBuilder, MetricDto metricDto, MeasureDto measureDto) { + double doubleValue; + String stringValue = null; + if (metricDto.isNumeric()) { + doubleValue = doubleValue(measureDto, metricDto.getKey()); + } else { + doubleValue = Double.NaN; + stringValue = measureDto.getString(metricDto.getKey()); + } + boolean onNewCode = metricDto.getKey().startsWith("new_"); + updateMeasureBuilder(measureBuilder, metricDto, doubleValue, stringValue, onNewCode); + } + + private static double doubleValue(MeasureDto measure, String metricKey) { + Double value = measure.getDouble(metricKey); + return value == null ? Double.NaN : value; + } + static void updateMeasureBuilder(Measure.Builder measureBuilder, MetricDto metric, double doubleValue, @Nullable String stringValue, boolean onNewCode) { measureBuilder.setMetric(metric.getKey()); Double bestValue = metric.getBestValue(); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MetricDtoWithBestValue.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MetricDtoWithBestValue.java index 7029a126c68..28f60996bad 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MetricDtoWithBestValue.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MetricDtoWithBestValue.java @@ -24,27 +24,24 @@ import java.util.Set; import java.util.function.Predicate; import org.sonar.api.resources.Qualifiers; import org.sonar.db.component.ComponentDto; -import org.sonar.db.measure.LiveMeasureDto; import org.sonar.db.metric.MetricDto; public class MetricDtoWithBestValue { private static final Set<String> QUALIFIERS_ELIGIBLE_FOR_BEST_VALUE = ImmutableSortedSet.of(Qualifiers.FILE, Qualifiers.UNIT_TEST_FILE); private final MetricDto metric; - private final LiveMeasureDto bestValue; + private final Double bestValue; MetricDtoWithBestValue(MetricDto metric) { this.metric = metric; - LiveMeasureDto measure = new LiveMeasureDto().setMetricUuid(metric.getUuid()); - measure.setValue(metric.getBestValue()); - this.bestValue = measure; + this.bestValue = metric.getBestValue(); } MetricDto getMetric() { return metric; } - LiveMeasureDto getBestValue() { + Double getBestValue() { return bestValue; } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/SearchAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/SearchAction.java index 52594af49db..35c7fd89aca 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/SearchAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/SearchAction.java @@ -35,7 +35,7 @@ import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDto; -import org.sonar.db.measure.LiveMeasureDto; +import org.sonar.db.measure.MeasureDto; import org.sonar.db.metric.MetricDto; import org.sonar.db.metric.RemovedMetricConverter; import org.sonar.server.user.UserSession; @@ -128,7 +128,7 @@ public class SearchAction implements MeasuresWsAction { private SearchRequest request; private List<ComponentDto> projects; private List<MetricDto> metrics; - private List<LiveMeasureDto> measures; + private List<MeasureDto> measures; ResponseBuilder(Request httpRequest, DbSession dbSession) { this.dbSession = dbSession; @@ -185,10 +185,10 @@ public class SearchAction implements MeasuresWsAction { .toList(); } - private List<LiveMeasureDto> searchMeasures() { - return dbClient.liveMeasureDao().selectByComponentUuidsAndMetricUuids(dbSession, + private List<MeasureDto> searchMeasures() { + return dbClient.measureDao().selectByComponentUuidsAndMetricKeys(dbSession, projects.stream().map(ComponentDto::uuid).toList(), - metrics.stream().map(MetricDto::getUuid).toList()); + metrics.stream().map(MetricDto::getKey).toList()); } private SearchWsResponse buildResponse() { @@ -201,21 +201,22 @@ public class SearchAction implements MeasuresWsAction { private List<Measure> buildWsMeasures() { Map<String, ComponentDto> componentsByUuid = projects.stream().collect(toMap(ComponentDto::uuid, Function.identity())); Map<String, String> componentNamesByKey = projects.stream().collect(toMap(ComponentDto::getKey, ComponentDto::name)); - Map<String, MetricDto> metricsByUuid = metrics.stream().collect(toMap(MetricDto::getUuid, identity())); + Map<String, MetricDto> metricsByKey = metrics.stream().collect(toMap(MetricDto::getKey, identity())); - Function<LiveMeasureDto, MetricDto> dbMeasureToDbMetric = dbMeasure -> metricsByUuid.get(dbMeasure.getMetricUuid()); Function<Measure, String> byMetricKey = Measure::getMetric; Function<Measure, String> byComponentName = wsMeasure -> componentNamesByKey.get(wsMeasure.getComponent()); Measure.Builder measureBuilder = Measure.newBuilder(); List<Measure> allMeasures = new ArrayList<>(); - for (LiveMeasureDto measure : measures) { - updateMeasureBuilder(measureBuilder, dbMeasureToDbMetric.apply(measure), measure); - measureBuilder.setComponent(componentsByUuid.get(measure.getComponentUuid()).getKey()); - Measure measureMsg = measureBuilder.build(); - addMeasureIncludingRenamedMetric(measureMsg, allMeasures, measureBuilder); - - measureBuilder.clear(); + for (MeasureDto measure : measures) { + for (String metricKey : measure.getMetricValues().keySet()) { + updateMeasureBuilder(measureBuilder, metricsByKey.get(metricKey), measure); + measureBuilder.setComponent(componentsByUuid.get(measure.getComponentUuid()).getKey()); + Measure measureMsg = measureBuilder.build(); + addMeasureIncludingRenamedMetric(measureMsg, allMeasures, measureBuilder); + + measureBuilder.clear(); + } } return allMeasures.stream() .sorted(comparing(byMetricKey).thenComparing(byComponentName)) diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/SearchMyProjectsAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/SearchMyProjectsAction.java index 42ab1b2cdd6..6aa328a0ed8 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/SearchMyProjectsAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/SearchMyProjectsAction.java @@ -40,7 +40,7 @@ import org.sonar.db.Pagination; import org.sonar.db.component.BranchDto; import org.sonar.db.component.ProjectLinkDto; import org.sonar.db.component.SnapshotDto; -import org.sonar.db.measure.LiveMeasureDto; +import org.sonar.db.measure.MeasureDto; import org.sonar.db.project.ProjectDto; import org.sonar.server.user.UserSession; import org.sonarqube.ws.Projects.SearchMyProjectsWsResponse; @@ -185,7 +185,7 @@ public class SearchMyProjectsAction implements ProjectsWsAction { Set<String> mainBranchUuids = branches.stream().map(BranchDto::getUuid).collect(Collectors.toSet()); List<SnapshotDto> snapshots = dbClient.snapshotDao() .selectLastAnalysesByRootComponentUuids(dbSession, mainBranchUuids); - List<LiveMeasureDto> qualityGates = dbClient.liveMeasureDao() + List<MeasureDto> qualityGates = dbClient.measureDao() .selectByComponentUuidsAndMetricKeys(dbSession, mainBranchUuids, singletonList(CoreMetrics.ALERT_STATUS_KEY)); data diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/SearchMyProjectsData.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/SearchMyProjectsData.java index e7af638be5e..ec1c3bcb027 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/SearchMyProjectsData.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/SearchMyProjectsData.java @@ -29,12 +29,13 @@ import java.util.stream.Collectors; import org.sonar.db.component.BranchDto; import org.sonar.db.component.ProjectLinkDto; import org.sonar.db.component.SnapshotDto; -import org.sonar.db.measure.LiveMeasureDto; +import org.sonar.db.measure.MeasureDto; import org.sonar.db.project.ProjectDto; import static com.google.common.collect.ImmutableList.copyOf; import static java.util.Objects.requireNonNull; import static java.util.function.Function.identity; +import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY; class SearchMyProjectsData { @@ -85,13 +86,14 @@ class SearchMyProjectsData { dtos.forEach(projectLink -> projectLinks.put(projectLink.getProjectUuid(), projectLink)); return projectLinks.build(); } + private static Map<String, String> buildBranchUuidByProjectUuidMap(List<BranchDto> branches) { return branches.stream().collect(Collectors.toMap(BranchDto::getProjectUuid, BranchDto::getUuid)); } - private static Map<String, String> buildQualityGateStatuses(List<LiveMeasureDto> measures) { + private static Map<String, String> buildQualityGateStatuses(List<MeasureDto> measures) { return ImmutableMap.copyOf(measures.stream() - .collect(Collectors.toMap(LiveMeasureDto::getComponentUuid, LiveMeasureDto::getDataAsString))); + .collect(Collectors.toMap(MeasureDto::getComponentUuid, m -> m.getString(ALERT_STATUS_KEY)))); } public String mainBranchUuidForProjectUuid(String projectUuid) { @@ -110,7 +112,7 @@ class SearchMyProjectsData { private List<BranchDto> branches; private List<ProjectLinkDto> projectLinks; private List<SnapshotDto> snapshots; - private List<LiveMeasureDto> qualityGates; + private List<MeasureDto> qualityGates; private Integer totalNbOfProjects; private Builder() { @@ -137,7 +139,7 @@ class SearchMyProjectsData { return this; } - public Builder setQualityGates(List<LiveMeasureDto> qGateStatuses) { + public Builder setQualityGates(List<MeasureDto> qGateStatuses) { this.qualityGates = qGateStatuses; return this; } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java index 9c034901fbf..c56ff41d1b4 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java @@ -35,7 +35,6 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.BranchDto; import org.sonar.db.component.SnapshotDto; -import org.sonar.db.measure.LiveMeasureDto; import org.sonar.db.measure.ProjectMeasureDto; import org.sonar.db.permission.GlobalPermission; import org.sonar.db.project.ProjectDto; @@ -216,8 +215,8 @@ public class ProjectStatusAction implements QualityGatesWsAction { } // do not restrict to a specified analysis, use the live measure - Optional<LiveMeasureDto> measure = dbClient.liveMeasureDao().selectMeasure(dbSession, projectAndSnapshot.branch.getUuid(), CoreMetrics.QUALITY_GATE_DETAILS_KEY); - return measure.map(LiveMeasureDto::getDataAsString); + return dbClient.measureDao().selectByComponentUuid(dbSession, projectAndSnapshot.branch.getUuid()) + .map(m -> m.getString(CoreMetrics.QUALITY_GATE_DETAILS_KEY)); } private void checkPermission(ProjectDto project) { diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ui/ws/ComponentAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ui/ws/ComponentAction.java index 5ace1980a30..9fed1e84f89 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ui/ws/ComponentAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ui/ws/ComponentAction.java @@ -47,7 +47,6 @@ import org.sonar.db.DbSession; import org.sonar.db.component.BranchDto; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.SnapshotDto; -import org.sonar.db.measure.LiveMeasureDto; import org.sonar.db.permission.GlobalPermission; import org.sonar.db.property.PropertyDto; import org.sonar.db.property.PropertyQuery; @@ -248,8 +247,8 @@ public class ComponentAction implements NavigationWsAction { } private void writeProfiles(JsonWriter json, DbSession dbSession, ComponentDto component) { - Set<QualityProfile> qualityProfiles = dbClient.liveMeasureDao().selectMeasure(dbSession, component.branchUuid(), QUALITY_PROFILES_KEY) - .map(LiveMeasureDto::getDataAsString) + Set<QualityProfile> qualityProfiles = dbClient.measureDao().selectByComponentUuid(dbSession, component.branchUuid()) + .map(m -> m.getString(QUALITY_PROFILES_KEY)) .map(data -> QPMeasureData.fromJson(data).getProfiles()) .orElse(emptySortedSet()); Map<String, QProfileDto> dtoByQPKey = dbClient.qualityProfileDao().selectByUuids(dbSession, qualityProfiles.stream().map(QualityProfile::getQpKey).toList()) diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java index 4cc8db8ba45..4daeb93fbd6 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java @@ -31,7 +31,6 @@ import org.sonar.api.measures.Metric.ValueType; import org.sonar.api.resources.Qualifiers; import org.sonar.core.util.Uuids; import org.sonar.db.component.ComponentDto; -import org.sonar.db.measure.LiveMeasureDto; import org.sonar.db.metric.MetricDto; import org.sonar.server.measure.ImpactMeasureBuilder; @@ -44,7 +43,7 @@ import static org.sonar.server.measure.ws.ComponentTreeAction.METRIC_SORT; import static org.sonar.server.measure.ws.ComponentTreeAction.NAME_SORT; import static org.sonar.server.measure.ws.ComponentTreeAction.PATH_SORT; import static org.sonar.server.measure.ws.ComponentTreeAction.QUALIFIER_SORT; -import static org.sonar.server.measure.ws.ComponentTreeData.Measure.createFromMeasureDto; +import static org.sonar.server.measure.ws.ComponentTreeData.Measure.createFromMetricValue; class ComponentTreeSortTest { private static final String NUM_METRIC_KEY = "violations"; @@ -93,11 +92,11 @@ class ComponentTreeSortTest { // same number than path field double currentValue = 9; for (ComponentDto component : components) { - measuresByComponentUuidAndMetric.put(component.uuid(), violationsMetric, createFromMeasureDto(new LiveMeasureDto().setValue(currentValue))); - measuresByComponentUuidAndMetric.put(component.uuid(), newViolationsMetric, createFromMeasureDto(new LiveMeasureDto().setValue(currentValue))); - measuresByComponentUuidAndMetric.put(component.uuid(), sqaleIndexMetric, createFromMeasureDto(new LiveMeasureDto().setData(String.valueOf(currentValue)))); - measuresByComponentUuidAndMetric.put(component.uuid(), reliabilityIssueMetric, createFromMeasureDto(new LiveMeasureDto().setData(buildJsonImpact((int) currentValue)))); - measuresByComponentUuidAndMetric.put(component.uuid(), newReliabilityIssueMetric, createFromMeasureDto(new LiveMeasureDto().setData(buildJsonImpact((int) currentValue)))); + measuresByComponentUuidAndMetric.put(component.uuid(), violationsMetric, createFromMetricValue(violationsMetric, currentValue)); + measuresByComponentUuidAndMetric.put(component.uuid(), newViolationsMetric, createFromMetricValue(newViolationsMetric, currentValue)); + measuresByComponentUuidAndMetric.put(component.uuid(), sqaleIndexMetric, createFromMetricValue(sqaleIndexMetric, currentValue)); + measuresByComponentUuidAndMetric.put(component.uuid(), reliabilityIssueMetric, createFromMetricValue(reliabilityIssueMetric, buildJsonImpact((int) currentValue))); + measuresByComponentUuidAndMetric.put(component.uuid(), newReliabilityIssueMetric, createFromMetricValue(newReliabilityIssueMetric, buildJsonImpact((int) currentValue))); currentValue--; } } @@ -191,7 +190,7 @@ class ComponentTreeSortTest { for (int i = 0; i < components.size(); i++) { ComponentDto component = components.get(i); String alertStatus = statuses.get(i % 2); - measuresByComponentUuidAndMetric.put(component.uuid(), metrics.get(0), createFromMeasureDto(new LiveMeasureDto().setData(alertStatus))); + measuresByComponentUuidAndMetric.put(component.uuid(), metrics.get(0), createFromMetricValue(metrics.get(0), alertStatus)); } ComponentTreeRequest wsRequest = newRequest(newArrayList(METRIC_SORT, NAME_SORT), true, CoreMetrics.ALERT_STATUS_KEY); diff --git a/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java index 3d0d5cfd82c..95e617507d1 100644 --- a/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java +++ b/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java @@ -294,6 +294,7 @@ import org.sonar.server.ws.ws.WebServicesWsModule; import org.sonar.telemetry.TelemetryClient; import org.sonar.telemetry.TelemetryDaemon; import org.sonar.telemetry.legacy.CloudUsageDataProvider; +import org.sonar.telemetry.legacy.ProjectLocDistributionDataProvider; import org.sonar.telemetry.legacy.QualityProfileDataProvider; import org.sonar.telemetry.legacy.TelemetryDataJsonWriter; import org.sonar.telemetry.legacy.TelemetryDataLoaderImpl; @@ -687,6 +688,7 @@ public class PlatformLevel4 extends PlatformLevel { TelemetryClient.class, CloudUsageDataProvider.class, QualityProfileDataProvider.class, + ProjectLocDistributionDataProvider.class, // monitoring ServerMonitoringMetrics.class, diff --git a/server/sonar-webserver/src/main/java/org/sonar/server/platform/telemetry/TelemetryNclocProvider.java b/server/sonar-webserver/src/main/java/org/sonar/server/platform/telemetry/TelemetryNclocProvider.java index 0d93c951d08..d06d2f18bb3 100644 --- a/server/sonar-webserver/src/main/java/org/sonar/server/platform/telemetry/TelemetryNclocProvider.java +++ b/server/sonar-webserver/src/main/java/org/sonar/server/platform/telemetry/TelemetryNclocProvider.java @@ -26,25 +26,22 @@ import java.util.Map; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.measure.ProjectLocDistributionDto; -import org.sonar.db.metric.MetricDto; import org.sonar.telemetry.core.Dimension; import org.sonar.telemetry.core.Granularity; import org.sonar.telemetry.core.TelemetryDataProvider; import org.sonar.telemetry.core.TelemetryDataType; - -import static java.util.Arrays.asList; -import static java.util.stream.Collectors.toMap; -import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; -import static org.sonar.api.measures.CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY; +import org.sonar.telemetry.legacy.ProjectLocDistributionDataProvider; public class TelemetryNclocProvider implements TelemetryDataProvider<Long> { public static final String METRIC_KEY = "ncloc_per_language"; private final DbClient dbClient; + private final ProjectLocDistributionDataProvider projectLocDistributionDataProvider; - public TelemetryNclocProvider(DbClient dbClient) { + public TelemetryNclocProvider(DbClient dbClient, ProjectLocDistributionDataProvider projectLocDistributionDataProvider) { this.dbClient = dbClient; + this.projectLocDistributionDataProvider = projectLocDistributionDataProvider; } @Override @@ -75,20 +72,11 @@ public class TelemetryNclocProvider implements TelemetryDataProvider<Long> { } private Map<String, Long> getNclocDistribution(DbSession dbSession) { - Map<String, String> metricUuidMap = getNclocMetricUuidMap(dbSession); - String nclocUuid = metricUuidMap.get(NCLOC_KEY); - String nclocDistributionUuid = metricUuidMap.get(NCLOC_LANGUAGE_DISTRIBUTION_KEY); - List<ProjectLocDistributionDto> branchesWithLargestNcloc = dbClient.liveMeasureDao().selectLargestBranchesLocDistribution(dbSession, nclocUuid, nclocDistributionUuid); + List<ProjectLocDistributionDto> branchesWithLargestNcloc = projectLocDistributionDataProvider.getProjectLocDistribution(dbSession); List<LanguageDistribution> languageDistributions = getLanguageDistributionList(branchesWithLargestNcloc); return getNclocDistributionPerLanguage(languageDistributions); } - private Map<String, String> getNclocMetricUuidMap(DbSession dbSession) { - return dbClient.metricDao().selectByKeys(dbSession, asList(NCLOC_KEY, NCLOC_LANGUAGE_DISTRIBUTION_KEY)) - .stream() - .collect(toMap(MetricDto::getKey, MetricDto::getUuid)); - } - private static List<LanguageDistribution> getLanguageDistributionList(List<ProjectLocDistributionDto> branchesWithLargestNcloc) { return branchesWithLargestNcloc.stream() .flatMap(measure -> Arrays.stream(measure.locDistribution().split(";")) diff --git a/server/sonar-webserver/src/test/java/org/sonar/server/platform/telemetry/TelemetryNclocProviderTest.java b/server/sonar-webserver/src/test/java/org/sonar/server/platform/telemetry/TelemetryNclocProviderTest.java index 5bab0a2cf3c..4273dbdbe0f 100644 --- a/server/sonar-webserver/src/test/java/org/sonar/server/platform/telemetry/TelemetryNclocProviderTest.java +++ b/server/sonar-webserver/src/test/java/org/sonar/server/platform/telemetry/TelemetryNclocProviderTest.java @@ -25,36 +25,29 @@ import org.mockito.Mockito; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.measure.ProjectLocDistributionDto; -import org.sonar.db.metric.MetricDto; import org.sonar.telemetry.core.Dimension; import org.sonar.telemetry.core.Granularity; +import org.sonar.telemetry.legacy.ProjectLocDistributionDataProvider; -import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; -import static org.sonar.api.measures.CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY; import static org.sonar.server.platform.telemetry.TelemetryNclocProvider.METRIC_KEY; class TelemetryNclocProviderTest { - DbClient dbClient = mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS); + private final DbClient dbClient = mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS); + private final ProjectLocDistributionDataProvider projectLocDistributionDataProvider = mock(ProjectLocDistributionDataProvider.class); private final DbSession dbSession = mock(DbSession.class); @Test void getValues_returnsTheRightLanguageDistribution() { - TelemetryNclocProvider telemetryNclocProvider = new TelemetryNclocProvider(dbClient); + TelemetryNclocProvider telemetryNclocProvider = new TelemetryNclocProvider(dbClient, projectLocDistributionDataProvider); when(dbClient.openSession(false)).thenReturn(dbSession); - when(dbClient.metricDao().selectByKeys(dbSession, asList(NCLOC_KEY, NCLOC_LANGUAGE_DISTRIBUTION_KEY))).thenReturn(Arrays.asList( - new MetricDto().setKey(NCLOC_KEY).setUuid("ncloc_uuid"), - new MetricDto().setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY).setUuid("ncloc_distribution_uuid") - )); - - when(dbClient.liveMeasureDao().selectLargestBranchesLocDistribution(dbSession, "ncloc_uuid", "ncloc_distribution_uuid")).thenReturn(Arrays.asList( + when(projectLocDistributionDataProvider.getProjectLocDistribution(dbSession)).thenReturn(Arrays.asList( new ProjectLocDistributionDto("project1", "branch1-p1", "java=5000;xml=1000;js=1000"), new ProjectLocDistributionDto("project2", "branch1-p2", "java=10000;csharp=2000"), new ProjectLocDistributionDto("project3", "branch1-p3", "java=7000;js=500") @@ -70,4 +63,5 @@ class TelemetryNclocProviderTest { assertThat(telemetryNclocProvider.getValues()).containsEntry("csharp", 2000L); assertThat(telemetryNclocProvider.getValues()).containsEntry("js", 1500L); } -}
\ No newline at end of file +} + |