diff options
11 files changed, 19 insertions, 867 deletions
diff --git a/gradle.properties b/gradle.properties index 0137300f22a..cc2e051b60b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ version=25.7 # 30 months from the release date for LTA versions # No change required for patch versions versionEOL=2027-01-31 -pluginApiVersion=12.0.0.2960 +pluginApiVersion=13.0.0.3026 description=Open source platform for continuous inspection of code quality projectTitle=SonarQube org.gradle.jvmargs=-Xmx2048m diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/AverageFormula.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/AverageFormula.java deleted file mode 100644 index 4dab14d2591..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/AverageFormula.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 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.ce.task.projectanalysis.formula; - -import java.util.Optional; -import org.sonar.ce.task.projectanalysis.measure.Measure; - -import static java.util.Objects.requireNonNull; - -public class AverageFormula implements Formula<AverageFormula.AverageCounter> { - - private final String outputMetricKey; - - private final String mainMetric; - private final String byMetric; - - private AverageFormula(Builder builder) { - this.outputMetricKey = builder.outputMetricKey; - this.mainMetric = builder.mainMetric; - this.byMetric = builder.byMetric; - } - - @Override - public AverageCounter createNewCounter() { - return new AverageCounter(); - } - - @Override - public Optional<Measure> createMeasure(AverageCounter counter, CreateMeasureContext context) { - Optional<Double> mainValueOptional = counter.getMainValue(); - Optional<Double> byValueOptional = counter.getByValue(); - if (mainValueOptional.isPresent() && byValueOptional.isPresent()) { - double mainValue = mainValueOptional.get(); - double byValue = byValueOptional.get(); - if (byValue > 0D) { - return Optional.of(Measure.newMeasureBuilder().create(mainValue / byValue, context.getMetric().getDecimalScale())); - } - } - return Optional.empty(); - } - - @Override - public String[] getOutputMetricKeys() { - return new String[] {outputMetricKey}; - } - - public static class Builder { - private String outputMetricKey; - private String mainMetric; - private String byMetric; - - private Builder() { - // prevents instantiation outside static method - } - - public static Builder newBuilder() { - return new Builder(); - } - - public Builder setOutputMetricKey(String m) { - this.outputMetricKey = m; - return this; - } - - public Builder setMainMetricKey(String m) { - this.mainMetric = m; - return this; - } - - public Builder setByMetricKey(String m) { - this.byMetric = m; - return this; - } - - public AverageFormula build() { - requireNonNull(outputMetricKey, "Output metric key cannot be null"); - requireNonNull(mainMetric, "Main metric Key cannot be null"); - requireNonNull(byMetric, "By metric Key cannot be null"); - return new AverageFormula(this); - } - } - - class AverageCounter implements Counter<AverageCounter> { - - private boolean initialized = false; - - private double mainValue = 0D; - private double byValue = 0D; - - @Override - public void aggregate(AverageCounter counter) { - addValuesIfPresent(counter.getMainValue(), counter.getByValue()); - } - - @Override - public void initialize(CounterInitializationContext context) { - Optional<Double> mainValueOptional = getDoubleValue(context.getMeasure(mainMetric)); - Optional<Double> byValueOptional = getDoubleValue(context.getMeasure(byMetric)); - addValuesIfPresent(mainValueOptional, byValueOptional); - } - - private void addValuesIfPresent(Optional<Double> counterMainValue, Optional<Double> counterByValue) { - if (counterMainValue.isPresent() && counterByValue.isPresent()) { - initialized = true; - mainValue += counterMainValue.get(); - byValue += counterByValue.get(); - } - } - - public Optional<Double> getMainValue() { - return getValue(mainValue); - } - - public Optional<Double> getByValue() { - return getValue(byValue); - } - - private Optional<Double> getValue(double value) { - if (initialized) { - return Optional.of(value); - } - return Optional.empty(); - } - - private Optional<Double> getDoubleValue(Optional<Measure> measureOptional) { - if (!measureOptional.isPresent()) { - return Optional.empty(); - } - Measure measure = measureOptional.get(); - switch (measure.getValueType()) { - case DOUBLE: - return Optional.of(measure.getDoubleValue()); - case LONG: - return Optional.of((double) measure.getLongValue()); - case INT: - return Optional.of((double) measure.getIntValue()); - case NO_VALUE: - return Optional.empty(); - default: - throw new IllegalArgumentException(String.format("Measure of type '%s' are not supported", measure.getValueType().name())); - } - } - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/DistributionFormula.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/DistributionFormula.java deleted file mode 100644 index d0d0bacd0bc..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/DistributionFormula.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 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.ce.task.projectanalysis.formula; - -import java.util.Optional; -import org.sonar.api.ce.measure.RangeDistributionBuilder; -import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.CrawlerDepthLimit; -import org.sonar.ce.task.projectanalysis.measure.Measure; - -import static java.util.Objects.requireNonNull; - -public class DistributionFormula implements Formula<DistributionFormula.DistributionCounter> { - - private final String metricKey; - - public DistributionFormula(String metricKey) { - this.metricKey = requireNonNull(metricKey, "Metric key cannot be null"); - } - - @Override - public DistributionCounter createNewCounter() { - return new DistributionCounter(); - } - - @Override - public Optional<Measure> createMeasure(DistributionCounter counter, CreateMeasureContext context) { - Component.Type componentType = context.getComponent().getType(); - Optional<String> value = counter.getValue(); - if (value.isPresent() && CrawlerDepthLimit.LEAVES.isDeeperThan(componentType)) { - return Optional.of(Measure.newMeasureBuilder().create(value.get())); - } - return Optional.empty(); - } - - @Override - public String[] getOutputMetricKeys() { - return new String[] {metricKey}; - } - - class DistributionCounter implements Counter<DistributionCounter> { - - private final RangeDistributionBuilder distribution = new RangeDistributionBuilder(); - private boolean initialized = false; - - @Override - public void aggregate(DistributionCounter counter) { - Optional<String> value = counter.getValue(); - if (value.isPresent()) { - initialized = true; - distribution.add(value.get()); - } - } - - @Override - public void initialize(CounterInitializationContext context) { - Optional<Measure> measureOptional = context.getMeasure(metricKey); - String data = measureOptional.isPresent() ? measureOptional.get().getData() : null; - if (data != null) { - initialized = true; - distribution.add(data); - } - } - - public Optional<String> getValue() { - if (initialized) { - return Optional.ofNullable(distribution.build()); - } - return Optional.empty(); - } - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/AverageFormulaExecutionTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/AverageFormulaExecutionTest.java deleted file mode 100644 index 519312ef9cb..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/AverageFormulaExecutionTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 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.ce.task.projectanalysis.formula; - -import com.google.common.collect.Lists; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.PathAwareCrawler; -import org.sonar.ce.task.projectanalysis.component.ReportComponent; -import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule; -import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule; -import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule; -import org.sonar.ce.task.projectanalysis.period.PeriodHolderRule; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_FUNCTIONS_KEY; -import static org.sonar.api.measures.CoreMetrics.FUNCTIONS_KEY; -import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_KEY; -import static org.sonar.ce.task.projectanalysis.component.Component.Type.DIRECTORY; -import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT; -import static org.sonar.ce.task.projectanalysis.component.ReportComponent.builder; -import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder; -import static org.sonar.ce.task.projectanalysis.measure.MeasureRepoEntry.entryOf; -import static org.sonar.ce.task.projectanalysis.measure.MeasureRepoEntry.toEntries; - -public class AverageFormulaExecutionTest { - - @Rule - public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); - @Rule - public MetricRepositoryRule metricRepository = new MetricRepositoryRule() - .add(CoreMetrics.FUNCTION_COMPLEXITY) - .add(CoreMetrics.COMPLEXITY_IN_FUNCTIONS) - .add(CoreMetrics.FUNCTIONS); - @Rule - public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository); - @Rule - public PeriodHolderRule periodsHolder = new PeriodHolderRule(); - - private FormulaExecutorComponentVisitor underTest; - - @Before - public void setUp() { - underTest = FormulaExecutorComponentVisitor.newBuilder(metricRepository, measureRepository) - .buildFor(Lists.newArrayList( - AverageFormula.Builder.newBuilder() - .setOutputMetricKey(FUNCTION_COMPLEXITY_KEY) - .setMainMetricKey(COMPLEXITY_IN_FUNCTIONS_KEY) - .setByMetricKey(FUNCTIONS_KEY) - .build())); - } - - @Test - public void add_measures() { - ReportComponent project = builder(PROJECT, 1) - .addChildren( - builder(DIRECTORY, 111) - .addChildren( - builder(Component.Type.FILE, 1111).build(), - builder(Component.Type.FILE, 1112).build()) - .build(), - builder(DIRECTORY, 121) - .addChildren( - builder(Component.Type.FILE, 1211).build()) - .build()) - .build(); - - treeRootHolder.setRoot(project); - - measureRepository.addRawMeasure(1111, COMPLEXITY_IN_FUNCTIONS_KEY, newMeasureBuilder().create(5)); - measureRepository.addRawMeasure(1111, FUNCTIONS_KEY, newMeasureBuilder().create(2)); - - measureRepository.addRawMeasure(1112, COMPLEXITY_IN_FUNCTIONS_KEY, newMeasureBuilder().create(1)); - measureRepository.addRawMeasure(1112, FUNCTIONS_KEY, newMeasureBuilder().create(1)); - - measureRepository.addRawMeasure(1211, COMPLEXITY_IN_FUNCTIONS_KEY, newMeasureBuilder().create(9)); - measureRepository.addRawMeasure(1211, FUNCTIONS_KEY, newMeasureBuilder().create(2)); - - new PathAwareCrawler<>(underTest).visit(project); - - assertThat(toEntries(measureRepository.getAddedRawMeasures(1))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(3d, 1))); - assertThat(toEntries(measureRepository.getAddedRawMeasures(111))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(2d, 1))); - assertThat(toEntries(measureRepository.getAddedRawMeasures(1111))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(2.5d, 1))); - assertThat(toEntries(measureRepository.getAddedRawMeasures(1112))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(1d, 1))); - assertThat(toEntries(measureRepository.getAddedRawMeasures(121))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(4.5d, 1))); - assertThat(toEntries(measureRepository.getAddedRawMeasures(1211))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(4.5d, 1))); - } - - @Test - public void not_add_measures_when_no_data_on_file() { - ReportComponent project = builder(PROJECT, 1) - .addChildren( - builder(DIRECTORY, 111) - .addChildren( - builder(Component.Type.FILE, 1111).build()) - .build()) - .build(); - - treeRootHolder.setRoot(project); - - new PathAwareCrawler<>(underTest).visit(project); - - assertThat(measureRepository.getAddedRawMeasures(1)).isEmpty(); - assertThat(measureRepository.getAddedRawMeasures(111)).isEmpty(); - assertThat(measureRepository.getAddedRawMeasures(1111)).isEmpty(); - } - -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/AverageFormulaTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/AverageFormulaTest.java deleted file mode 100644 index 7d830eac3d5..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/AverageFormulaTest.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 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.ce.task.projectanalysis.formula; - -import java.util.Optional; -import org.junit.Test; -import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.ReportComponent; -import org.sonar.ce.task.projectanalysis.measure.Measure; -import org.sonar.ce.task.projectanalysis.metric.Metric; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_FUNCTIONS_KEY; -import static org.sonar.api.measures.CoreMetrics.FUNCTIONS_KEY; -import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_KEY; -import static org.sonar.ce.task.projectanalysis.formula.AverageFormula.Builder; - -public class AverageFormulaTest { - - private static final AverageFormula BASIC_AVERAGE_FORMULA = Builder.newBuilder() - .setOutputMetricKey(FUNCTION_COMPLEXITY_KEY) - .setMainMetricKey(COMPLEXITY_IN_FUNCTIONS_KEY) - .setByMetricKey(FUNCTIONS_KEY) - .build(); - - CounterInitializationContext counterInitializationContext = mock(CounterInitializationContext.class); - CreateMeasureContext createMeasureContext = new DumbCreateMeasureContext( - ReportComponent.builder(Component.Type.PROJECT, 1).build(), mock(Metric.class)); - - - @Test - public void fail_with_NPE_when_building_formula_without_output_metric() { - assertThatThrownBy(() -> { - Builder.newBuilder() - .setOutputMetricKey(null) - .setMainMetricKey(COMPLEXITY_IN_FUNCTIONS_KEY) - .setByMetricKey(FUNCTIONS_KEY) - .build(); - }) - .isInstanceOf(NullPointerException.class) - .hasMessage("Output metric key cannot be null"); - } - - @Test - public void fail_with_NPE_when_building_formula_without_main_metric() { - assertThatThrownBy(() -> { - Builder.newBuilder() - .setOutputMetricKey(FUNCTION_COMPLEXITY_KEY) - .setMainMetricKey(null) - .setByMetricKey(FUNCTIONS_KEY) - .build(); - }) - .isInstanceOf(NullPointerException.class) - .hasMessage("Main metric Key cannot be null"); - } - - @Test - public void fail_with_NPE_when_building_formula_without_by_metric() { - assertThatThrownBy(() -> { - Builder.newBuilder() - .setOutputMetricKey(FUNCTION_COMPLEXITY_KEY) - .setMainMetricKey(COMPLEXITY_IN_FUNCTIONS_KEY) - .setByMetricKey(null) - .build(); - }) - .isInstanceOf(NullPointerException.class) - .hasMessage("By metric Key cannot be null"); - } - - @Test - public void check_new_counter_class() { - assertThat(BASIC_AVERAGE_FORMULA.createNewCounter().getClass()).isEqualTo(AverageFormula.AverageCounter.class); - } - - @Test - public void check_output_metric_key_is_function_complexity_key() { - assertThat(BASIC_AVERAGE_FORMULA.getOutputMetricKeys()).containsOnly(FUNCTION_COMPLEXITY_KEY); - } - - @Test - public void create_measure_when_counter_is_aggregated_from_context() { - AverageFormula.AverageCounter counter = BASIC_AVERAGE_FORMULA.createNewCounter(); - addMeasure(COMPLEXITY_IN_FUNCTIONS_KEY, 10d); - addMeasure(FUNCTIONS_KEY, 2d); - counter.initialize(counterInitializationContext); - - assertThat(BASIC_AVERAGE_FORMULA.createMeasure(counter, createMeasureContext).get().getDoubleValue()).isEqualTo(5d); - } - - @Test - public void create_measure_when_counter_is_aggregated_from_another_counter() { - AverageFormula.AverageCounter anotherCounter = BASIC_AVERAGE_FORMULA.createNewCounter(); - addMeasure(COMPLEXITY_IN_FUNCTIONS_KEY, 10d); - addMeasure(FUNCTIONS_KEY, 2d); - anotherCounter.initialize(counterInitializationContext); - - AverageFormula.AverageCounter counter = BASIC_AVERAGE_FORMULA.createNewCounter(); - counter.aggregate(anotherCounter); - - assertThat(BASIC_AVERAGE_FORMULA.createMeasure(counter, createMeasureContext).get().getDoubleValue()).isEqualTo(5d); - } - - @Test - public void create_double_measure() { - AverageFormula.AverageCounter counter = BASIC_AVERAGE_FORMULA.createNewCounter(); - addMeasure(COMPLEXITY_IN_FUNCTIONS_KEY, 10d); - addMeasure(FUNCTIONS_KEY, 2d); - counter.initialize(counterInitializationContext); - - assertThat(BASIC_AVERAGE_FORMULA.createMeasure(counter, createMeasureContext).get().getDoubleValue()).isEqualTo(5d); - } - - @Test - public void create_integer_measure() { - AverageFormula.AverageCounter counter = BASIC_AVERAGE_FORMULA.createNewCounter(); - addMeasure(COMPLEXITY_IN_FUNCTIONS_KEY, 10); - addMeasure(FUNCTIONS_KEY, 2); - counter.initialize(counterInitializationContext); - - assertThat(BASIC_AVERAGE_FORMULA.createMeasure(counter, createMeasureContext).get().getDoubleValue()).isEqualTo(5); - } - - @Test - public void create_long_measure() { - AverageFormula.AverageCounter counter = BASIC_AVERAGE_FORMULA.createNewCounter(); - addMeasure(COMPLEXITY_IN_FUNCTIONS_KEY, 10L); - addMeasure(FUNCTIONS_KEY, 2L); - counter.initialize(counterInitializationContext); - - assertThat(BASIC_AVERAGE_FORMULA.createMeasure(counter, createMeasureContext).get().getDoubleValue()).isEqualTo(5L); - } - - @Test - public void not_create_measure_when_aggregated_measure_has_no_value() { - AverageFormula.AverageCounter counter = BASIC_AVERAGE_FORMULA.createNewCounter(); - addMeasure(COMPLEXITY_IN_FUNCTIONS_KEY, 10L); - when(counterInitializationContext.getMeasure(FUNCTIONS_KEY)).thenReturn(Optional.of(Measure.newMeasureBuilder().createNoValue())); - counter.initialize(counterInitializationContext); - - assertThat(BASIC_AVERAGE_FORMULA.createMeasure(counter, createMeasureContext)).isNotPresent(); - } - - @Test - public void fail_with_IAE_when_aggregate_from_component_and_context_with_not_numeric_measures() { - assertThatThrownBy(() -> { - AverageFormula.AverageCounter counter = BASIC_AVERAGE_FORMULA.createNewCounter(); - addMeasure(COMPLEXITY_IN_FUNCTIONS_KEY, 10L); - when(counterInitializationContext.getMeasure(FUNCTIONS_KEY)).thenReturn(Optional.of(Measure.newMeasureBuilder().create("data"))); - counter.initialize(counterInitializationContext); - - BASIC_AVERAGE_FORMULA.createMeasure(counter, createMeasureContext); - }) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Measure of type 'STRING' are not supported"); - } - - @Test - public void no_measure_created_when_counter_has_no_value() { - AverageFormula.AverageCounter counter = BASIC_AVERAGE_FORMULA.createNewCounter(); - when(counterInitializationContext.getMeasure(anyString())).thenReturn(Optional.empty()); - counter.initialize(counterInitializationContext); - - assertThat(BASIC_AVERAGE_FORMULA.createMeasure(counter, createMeasureContext)).isNotPresent(); - } - - @Test - public void not_create_measure_when_only_one_measure() { - AverageFormula.AverageCounter counter = BASIC_AVERAGE_FORMULA.createNewCounter(); - addMeasure(COMPLEXITY_IN_FUNCTIONS_KEY, 10L); - when(counterInitializationContext.getMeasure(FUNCTIONS_KEY)).thenReturn(Optional.empty()); - counter.initialize(counterInitializationContext); - - assertThat(BASIC_AVERAGE_FORMULA.createMeasure(counter, createMeasureContext)).isNotPresent(); - } - - @Test - public void not_create_measure_when_by_value_is_zero() { - AverageFormula.AverageCounter counter = BASIC_AVERAGE_FORMULA.createNewCounter(); - addMeasure(COMPLEXITY_IN_FUNCTIONS_KEY, 10d); - addMeasure(FUNCTIONS_KEY, 0d); - counter.initialize(counterInitializationContext); - - assertThat(BASIC_AVERAGE_FORMULA.createMeasure(counter, createMeasureContext)).isNotPresent(); - } - - private void addMeasure(String metricKey, double value) { - when(counterInitializationContext.getMeasure(metricKey)).thenReturn(Optional.of(Measure.newMeasureBuilder().create(value, 1))); - } - - private void addMeasure(String metricKey, int value) { - when(counterInitializationContext.getMeasure(metricKey)).thenReturn(Optional.of(Measure.newMeasureBuilder().create(value))); - } - - private void addMeasure(String metricKey, long value) { - when(counterInitializationContext.getMeasure(metricKey)).thenReturn(Optional.of(Measure.newMeasureBuilder().create(value))); - } - -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/DistributionFormulaExecutionTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/DistributionFormulaExecutionTest.java deleted file mode 100644 index a406c0dc6f5..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/DistributionFormulaExecutionTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 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.ce.task.projectanalysis.formula; - -import com.google.common.collect.Lists; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.PathAwareCrawler; -import org.sonar.ce.task.projectanalysis.component.ReportComponent; -import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule; -import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule; -import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY; -import static org.sonar.ce.task.projectanalysis.component.Component.Type.DIRECTORY; -import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT; -import static org.sonar.ce.task.projectanalysis.component.ReportComponent.builder; -import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder; -import static org.sonar.ce.task.projectanalysis.measure.MeasureRepoEntry.entryOf; -import static org.sonar.ce.task.projectanalysis.measure.MeasureRepoEntry.toEntries; - -public class DistributionFormulaExecutionTest { - - @Rule - public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); - @Rule - public MetricRepositoryRule metricRepository = new MetricRepositoryRule().add(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION); - @Rule - public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository); - - FormulaExecutorComponentVisitor underTest; - - @Before - public void setUp() throws Exception { - underTest = FormulaExecutorComponentVisitor.newBuilder(metricRepository, measureRepository) - .buildFor(Lists.newArrayList(new DistributionFormula(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY))); - } - - @Test - public void add_measures() { - ReportComponent project = builder(PROJECT, 1) - .addChildren( - builder(DIRECTORY, 11) - .addChildren( - builder(DIRECTORY, 111) - .addChildren( - builder(Component.Type.FILE, 1111).build(), - builder(Component.Type.FILE, 1112).build()) - .build()) - .build(), - builder(DIRECTORY, 12) - .addChildren( - builder(DIRECTORY, 121) - .addChildren( - builder(Component.Type.FILE, 1211).build()) - .build()) - .build()) - .build(); - - treeRootHolder.setRoot(project); - - measureRepository.addRawMeasure(1111, FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=3;3.5=5;6.5=9")); - measureRepository.addRawMeasure(1112, FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=0;3.5=2;6.5=1")); - measureRepository.addRawMeasure(1211, FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=1;3.5=3;6.5=2")); - - new PathAwareCrawler<>(underTest).visit(project); - - assertThat(toEntries(measureRepository.getAddedRawMeasures(1))).containsOnly(entryOf(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=4;3.5=10;6.5=12"))); - assertThat(toEntries(measureRepository.getAddedRawMeasures(11))).containsOnly(entryOf(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=3;3.5=7;6.5=10"))); - assertThat(toEntries(measureRepository.getAddedRawMeasures(111))).containsOnly(entryOf(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=3;3.5=7;6.5=10"))); - assertThat(measureRepository.getAddedRawMeasures(1111)).isEmpty(); - assertThat(measureRepository.getAddedRawMeasures(1112)).isEmpty(); - assertThat(toEntries(measureRepository.getAddedRawMeasures(12))).containsOnly(entryOf(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=1;3.5=3;6.5=2"))); - assertThat(toEntries(measureRepository.getAddedRawMeasures(121))).containsOnly(entryOf(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=1;3.5=3;6.5=2"))); - assertThat(measureRepository.getAddedRawMeasures(1211)).isEmpty(); - } - - @Test - public void not_add_measures_when_no_data_on_file() { - ReportComponent project = builder(PROJECT, 1) - .addChildren( - builder(DIRECTORY, 11) - .addChildren( - builder(DIRECTORY, 111) - .addChildren( - builder(Component.Type.FILE, 1111).build()) - .build()) - .build()) - .build(); - - treeRootHolder.setRoot(project); - - new PathAwareCrawler<>(underTest).visit(project); - - assertThat(measureRepository.getAddedRawMeasures(1)).isEmpty(); - assertThat(measureRepository.getAddedRawMeasures(11)).isEmpty(); - assertThat(measureRepository.getAddedRawMeasures(111)).isEmpty(); - assertThat(measureRepository.getAddedRawMeasures(1111)).isEmpty(); - } - -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/DistributionFormulaTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/DistributionFormulaTest.java deleted file mode 100644 index 89df9c43f79..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/DistributionFormulaTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 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.ce.task.projectanalysis.formula; - -import java.util.Optional; -import org.junit.Test; -import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.ReportComponent; -import org.sonar.ce.task.projectanalysis.measure.Measure; -import org.sonar.ce.task.projectanalysis.metric.Metric; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY; - -public class DistributionFormulaTest { - - private static final DistributionFormula BASIC_DISTRIBUTION_FORMULA = new DistributionFormula(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY); - - - CounterInitializationContext counterInitializationContext = mock(CounterInitializationContext.class); - CreateMeasureContext projectCreateMeasureContext = new DumbCreateMeasureContext( - ReportComponent.builder(Component.Type.PROJECT, 1).build(), mock(Metric.class)); - CreateMeasureContext fileCreateMeasureContext = new DumbCreateMeasureContext( - ReportComponent.builder(Component.Type.FILE, 1).build(), mock(Metric.class)); - - @Test - public void check_new_counter_class() { - assertThat(BASIC_DISTRIBUTION_FORMULA.createNewCounter().getClass()).isEqualTo(DistributionFormula.DistributionCounter.class); - } - - @Test - public void fail_with_NPE_when_creating_counter_with_null_metric() { - assertThatThrownBy(() -> new DistributionFormula(null)) - .isInstanceOf(NullPointerException.class) - .hasMessage("Metric key cannot be null"); - } - - @Test - public void check_output_metric_key_is_function_complexity_distribution() { - assertThat(BASIC_DISTRIBUTION_FORMULA.getOutputMetricKeys()).containsOnly(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY); - } - - @Test - public void create_measure() { - DistributionFormula.DistributionCounter counter = BASIC_DISTRIBUTION_FORMULA.createNewCounter(); - addMeasure(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, "0=3;3=7;6=10"); - counter.initialize(counterInitializationContext); - - assertThat(BASIC_DISTRIBUTION_FORMULA.createMeasure(counter, projectCreateMeasureContext).get().getData()).isEqualTo("0=3;3=7;6=10"); - } - - @Test - public void create_measure_when_counter_is_aggregating_from_another_counter() { - DistributionFormula.DistributionCounter anotherCounter = BASIC_DISTRIBUTION_FORMULA.createNewCounter(); - addMeasure(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, "0=3;3=7;6=10"); - anotherCounter.initialize(counterInitializationContext); - - DistributionFormula.DistributionCounter counter = BASIC_DISTRIBUTION_FORMULA.createNewCounter(); - counter.aggregate(anotherCounter); - - assertThat(BASIC_DISTRIBUTION_FORMULA.createMeasure(counter, projectCreateMeasureContext).get().getData()).isEqualTo("0=3;3=7;6=10"); - } - - @Test - public void create_no_measure_when_no_value() { - DistributionFormula.DistributionCounter counter = BASIC_DISTRIBUTION_FORMULA.createNewCounter(); - when(counterInitializationContext.getMeasure(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY)).thenReturn(Optional.empty()); - counter.initialize(counterInitializationContext); - - assertThat(BASIC_DISTRIBUTION_FORMULA.createMeasure(counter, projectCreateMeasureContext)).isNotPresent(); - } - - @Test - public void not_create_measure_when_on_file() { - DistributionFormula.DistributionCounter counter = BASIC_DISTRIBUTION_FORMULA.createNewCounter(); - addMeasure(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, "0=3;3=7;6=10"); - counter.initialize(counterInitializationContext); - - assertThat(BASIC_DISTRIBUTION_FORMULA.createMeasure(counter, fileCreateMeasureContext)).isNotPresent(); - } - - private void addMeasure(String metricKey, String value) { - when(counterInitializationContext.getMeasure(metricKey)).thenReturn(Optional.of(Measure.newMeasureBuilder().create(value))); - } - -} diff --git a/server/sonar-webserver-core/src/it/java/org/sonar/server/startup/RegisterMetricsIT.java b/server/sonar-webserver-core/src/it/java/org/sonar/server/startup/RegisterMetricsIT.java index 1278205a383..814f5b2b20d 100644 --- a/server/sonar-webserver-core/src/it/java/org/sonar/server/startup/RegisterMetricsIT.java +++ b/server/sonar-webserver-core/src/it/java/org/sonar/server/startup/RegisterMetricsIT.java @@ -44,7 +44,6 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; public class RegisterMetricsIT { - public static final int SOON_TO_BE_REMOVED_COMPLEXITY_METRICS_COUNT = 7; @Rule public DbTester dbTester = DbTester.create(System2.INSTANCE); @@ -144,9 +143,7 @@ public class RegisterMetricsIT { .isEqualTo(CoreMetrics.getMetrics().size() // Metric CoreMetrics.WONT_FIX_ISSUES was renamed to CoreMetrics.ACCEPTED_ISSUES in 10.3. // We don't want to insert it anymore - - 1 - // SONAR-12647 We are exclusing complexity metrics, they will be removed from the plugin API soon - - SOON_TO_BE_REMOVED_COMPLEXITY_METRICS_COUNT); + - 1); } @Test diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/startup/RegisterMetrics.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/startup/RegisterMetrics.java index 05fcb23d55c..08965b0c895 100644 --- a/server/sonar-webserver-core/src/main/java/org/sonar/server/startup/RegisterMetrics.java +++ b/server/sonar-webserver-core/src/main/java/org/sonar/server/startup/RegisterMetrics.java @@ -20,11 +20,10 @@ package org.sonar.server.startup; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.FluentIterable; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import org.sonar.api.Startable; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Metric; @@ -39,24 +38,12 @@ import org.sonar.db.metric.MetricDto; import org.sonar.server.metric.MetricToDto; import org.springframework.beans.factory.annotation.Autowired; -import static com.google.common.collect.FluentIterable.concat; import static com.google.common.collect.Lists.newArrayList; import static org.sonar.db.metric.RemovedMetricConverter.REMOVED_METRIC; public class RegisterMetrics implements Startable { private static final Logger LOG = Loggers.get(RegisterMetrics.class); - /** - * Those metrics will be removed soon from the plugin API, so let's not register them in the database - */ - private static final Set<String> SOON_TO_BE_REMOVED_FROM_CORE_API_METRIC = Set.of( - CoreMetrics.COMPLEXITY_IN_CLASSES_KEY, - CoreMetrics.COMPLEXITY_IN_FUNCTIONS_KEY, - CoreMetrics.FILE_COMPLEXITY_DISTRIBUTION_KEY, - CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, - CoreMetrics.FUNCTION_COMPLEXITY_KEY, - CoreMetrics.CLASS_COMPLEXITY_KEY, - CoreMetrics.FILE_COMPLEXITY_KEY); private final DbClient dbClient; private final UuidFactory uuidFactory; @@ -79,8 +66,10 @@ public class RegisterMetrics implements Startable { @Override public void start() { - FluentIterable<Metric> metricsToRegister = concat(getCoreMetrics(), getPluginMetrics()) - .filter(m -> !REMOVED_METRIC.equals(m.getKey())); + List<Metric> metricsToRegister = new ArrayList<>(); + metricsToRegister.addAll(CoreMetrics.getMetrics()); + metricsToRegister.addAll(getPluginMetrics()); + metricsToRegister.removeIf(m -> REMOVED_METRIC.equals(m.getKey())); register(metricsToRegister); } @@ -131,13 +120,6 @@ public class RegisterMetrics implements Startable { } } - private static List<Metric> getCoreMetrics() { - return CoreMetrics.getMetrics() - .stream() - .filter(m -> !SOON_TO_BE_REMOVED_FROM_CORE_API_METRIC.contains(m.getKey())) - .toList(); - } - @VisibleForTesting List<Metric> getPluginMetrics() { List<Metric> metricsToRegister = newArrayList(); @@ -153,7 +135,7 @@ public class RegisterMetrics implements Startable { private static void checkMetrics(Map<String, Metrics> metricsByRepository, Metrics metrics) { for (Metric metric : metrics.getMetrics()) { String metricKey = metric.getKey(); - if (getCoreMetrics().contains(metric)) { + if (CoreMetrics.getMetrics().contains(metric)) { throw new IllegalStateException(String.format("Metric [%s] is already defined by SonarQube", metricKey)); } Metrics anotherRepository = metricsByRepository.get(metricKey); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualitygate/QualityGateCaycCheckerIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualitygate/QualityGateCaycCheckerIT.java index 343e1854127..7b660e38620 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualitygate/QualityGateCaycCheckerIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualitygate/QualityGateCaycCheckerIT.java @@ -39,7 +39,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.sonar.api.measures.CoreMetrics.BLOCKER_VIOLATIONS; import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES; -import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY; import static org.sonar.api.measures.CoreMetrics.LINE_COVERAGE; import static org.sonar.api.measures.CoreMetrics.NEW_COVERAGE; import static org.sonar.api.measures.CoreMetrics.NEW_DUPLICATED_LINES_DENSITY; @@ -107,7 +106,7 @@ public class QualityGateCaycCheckerIT { @Test public void isCaycCondition_when_check_non_compliant_condition_should_return_false() { - List.of(BLOCKER_VIOLATIONS, FUNCTION_COMPLEXITY) + List.of(BLOCKER_VIOLATIONS) .stream().map(this::toMetricDto) .forEach(metricDto -> assertFalse(underTest.isCaycCondition(metricDto))); } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java index e769e0d6451..355fb2cde0e 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java @@ -19,16 +19,6 @@ */ package org.sonar.scanner.sensor; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.data.MapEntry.entry; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - import java.io.File; import java.util.ArrayList; import java.util.List; @@ -77,6 +67,16 @@ import org.sonar.scanner.repository.ContextPropertiesCache; import org.sonar.scanner.repository.TelemetryCache; import org.sonar.scanner.scan.branch.BranchConfiguration; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.data.MapEntry.entry; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + class DefaultSensorStorageTest { @TempDir @@ -97,7 +97,6 @@ class DefaultSensorStorageTest { public void prepare() { MetricFinder metricFinder = mock(MetricFinder.class); when(metricFinder.<Integer>findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC); - when(metricFinder.<String>findByKey(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY)).thenReturn(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION); when(metricFinder.<Integer>findByKey(CoreMetrics.LINES_TO_COVER_KEY)).thenReturn(CoreMetrics.LINES_TO_COVER); settings = new MapSettings(); |