Browse Source

SONAR-16455 Merge measure's 'variation' and 'value'

tags/9.8.0.63668
Duarte Meneses 1 year ago
parent
commit
9b62ebf336
100 changed files with 1096 additions and 1550 deletions
  1. 10
    0
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/FileStatusesImpl.java
  2. 0
    83
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/VariationSumFormula.java
  3. 8
    8
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/coverage/CoverageUtils.java
  4. 0
    48
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/coverage/CoverageVariationFormula.java
  5. 0
    49
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/coverage/ElementsAndCoveredElementsVariationCounter.java
  6. 0
    48
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/coverage/LinesAndConditionsWithUncoveredVariationCounter.java
  7. 0
    46
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/coverage/LinesAndConditionsWithUncoveredVariationFormula.java
  8. 0
    41
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/coverage/SingleWithUncoveredVariationCounter.java
  9. 0
    46
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/coverage/SingleWithUncoveredVariationFormula.java
  10. 4
    7
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/IssueCounter.java
  11. 6
    6
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/NewEffortAggregator.java
  12. 0
    9
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/BestValueOptimization.java
  13. 28
    38
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/LiveMeasureDtoToMeasure.java
  14. 18
    97
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/Measure.java
  15. 0
    8
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/MeasureDtoToMeasure.java
  16. 0
    6
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/MeasureToMeasureDto.java
  17. 2
    27
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitygate/ConditionEvaluator.java
  18. 6
    9
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewMaintainabilityMeasuresVisitor.java
  19. 1
    1
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewReliabilityAndSecurityRatingMeasuresVisitor.java
  20. 4
    4
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewSecurityReviewMeasuresVisitor.java
  21. 7
    7
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/NewCoverageMeasuresStep.java
  22. 6
    6
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/NewSizeMeasuresStep.java
  23. 1
    1
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistLiveMeasuresStep.java
  24. 1
    1
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/SmallChangesetQualityGateSpecialCase.java
  25. 8
    7
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectexport/steps/ExportLiveMeasuresStep.java
  26. 8
    6
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectexport/steps/ExportMeasuresStep.java
  27. 7
    87
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/ReportFormulaExecutorComponentVisitorTest.java
  28. 2
    37
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/ViewsFormulaExecutorComponentVisitorTest.java
  29. 20
    20
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/counter/IntValueTest.java
  30. 13
    13
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/counter/RatingValueTest.java
  31. 0
    20
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/coverage/CoverageUtilsTest.java
  32. 6
    13
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/IssueCounterTest.java
  33. 14
    15
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/NewEffortAggregatorTest.java
  34. 6
    29
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/BestValueOptimizationTest.java
  35. 0
    41
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/LiveMeasureDtoToMeasureTest.java
  36. 0
    23
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureDtoToMeasureTest.java
  37. 0
    7
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureTest.java
  38. 0
    16
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureToMeasureDtoTest.java
  39. 1
    44
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitygate/ConditionEvaluatorTest.java
  40. 10
    10
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewMaintainabilityMeasuresVisitorTest.java
  41. 1
    2
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewReliabilityAndSecurityRatingMeasuresVisitorTest.java
  42. 6
    6
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewSecurityReviewMeasuresVisitorTest.java
  43. 50
    48
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/NewCoverageMeasuresStepTest.java
  44. 49
    48
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/NewSizeMeasuresStepTest.java
  45. 2
    3
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistLiveMeasuresStepTest.java
  46. 2
    3
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistMeasuresStepTest.java
  47. 1
    3
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/QualityGateMeasuresStepTest.java
  48. 5
    5
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/SmallChangesetQualityGateSpecialCaseTest.java
  49. 6
    6
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectexport/steps/ExportLiveMeasuresStepTest.java
  50. 34
    4
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectexport/steps/ExportMeasuresStepTest.java
  51. 19
    40
      server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/measure/MeasureAssert.java
  52. 0
    15
      server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/measure/MeasureRepoEntry.java
  53. 0
    13
      server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDto.java
  54. 0
    12
      server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDto.java
  55. 6
    7
      server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMeasuresIndexerIterator.java
  56. 1
    9
      server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml
  57. 1
    4
      server/sonar-db-dao/src/main/resources/org/sonar/db/measure/MeasureMapper.xml
  58. 0
    2
      server/sonar-db-dao/src/schema/schema-sq.ddl
  59. 4
    54
      server/sonar-db-dao/src/test/java/org/sonar/db/measure/LiveMeasureDaoTest.java
  60. 1
    4
      server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDtoTest.java
  61. 4
    4
      server/sonar-db-dao/src/test/java/org/sonar/db/measure/ProjectMeasuresIndexerIteratorTest.java
  62. 2
    4
      server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureTesting.java
  63. 2
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java
  64. 35
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v98/DbVersion98.java
  65. 33
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v98/DropLiveMeasureVariationColumn.java
  66. 33
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v98/DropProjectMeasureVariationColumn.java
  67. 28
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v98/MoveLiveMeasureVariationToValue.java
  68. 28
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v98/MoveProjectMeasureVariationToValue.java
  69. 65
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v98/VariationMigration.java
  70. 42
    0
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v98/DbVersion98Test.java
  71. 53
    0
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v98/DropLiveMeasureVariationColumnTest.java
  72. 53
    0
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v98/DropProjectMeasureVariationColumnTest.java
  73. 80
    0
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v98/MoveLiveMeasureVariationToValueTest.java
  74. 78
    0
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v98/MoveProjectMeasureVariationToValueTest.java
  75. 16
    0
      server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v98/DropLiveMeasureVariationColumnTest/schema.sql
  76. 17
    0
      server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v98/DropProjectMeasureVariationColumnTest/schema.sql
  77. 16
    0
      server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v98/MoveLiveMeasureVariationToValueTest/schema.sql
  78. 17
    0
      server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v98/MoveProjectMeasureVariationToValueTest/schema.sql
  79. 1
    1
      server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/ConditionEvaluator.java
  80. 0
    2
      server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/QualityGateEvaluator.java
  81. 2
    2
      server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/QualityGateEvaluatorImpl.java
  82. 8
    23
      server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/ConditionEvaluatorTest.java
  83. 0
    13
      server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/FakeMeasure.java
  84. 5
    6
      server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/QualityGateEvaluatorImplTest.java
  85. 10
    39
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/LiveMeasureTreeUpdaterImpl.java
  86. 0
    8
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/LiveQualityGateComputerImpl.java
  87. 1
    12
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/MeasureMatrix.java
  88. 0
    8
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/MeasureUpdateFormula.java
  89. 37
    52
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/MeasureUpdateFormulaFactoryImpl.java
  90. 3
    2
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java
  91. 2
    12
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java
  92. 2
    2
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeSort.java
  93. 4
    24
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/HasMeasure.java
  94. 23
    23
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java
  95. 1
    9
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MetricDtoWithBestValue.java
  96. 4
    8
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/PrMeasureFix.java
  97. 1
    4
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/SearchHistoryResponseFactory.java
  98. 3
    10
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/SearchHistoryResult.java
  99. 2
    10
      server/sonar-webserver-webapi/src/main/resources/org/sonar/server/measure/ws/component-example.json
  100. 0
    0
      server/sonar-webserver-webapi/src/main/resources/org/sonar/server/measure/ws/component_tree-example.json

+ 10
- 0
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/FileStatusesImpl.java View File

@@ -22,6 +22,8 @@ package org.sonar.ce.task.projectanalysis.component;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
import org.sonar.ce.task.projectanalysis.source.SourceHashRepository;
import org.sonar.db.source.FileHashesDto;
@@ -30,11 +32,14 @@ import static com.google.common.base.Preconditions.checkState;
import static org.sonar.ce.task.projectanalysis.component.ComponentVisitor.Order.PRE_ORDER;

public class FileStatusesImpl implements FileStatuses {
private static final Logger LOG = Loggers.get(FileStatusesImpl.class);

private final PreviousSourceHashRepository previousSourceHashRepository;
private final SourceHashRepository sourceHashRepository;
private final AnalysisMetadataHolder analysisMetadataHolder;
private final TreeRootHolder treeRootHolder;
private Set<String> fileUuidsMarkedAsUnchanged;
private int notMarkedAsUnchanged = 0;

public FileStatusesImpl(AnalysisMetadataHolder analysisMetadataHolder, TreeRootHolder treeRootHolder, PreviousSourceHashRepository previousSourceHashRepository,
SourceHashRepository sourceHashRepository) {
@@ -49,6 +54,8 @@ public class FileStatusesImpl implements FileStatuses {
if (!analysisMetadataHolder.isPullRequest() && !analysisMetadataHolder.isFirstAnalysis()) {
new DepthTraversalTypeAwareCrawler(new Visitor()).visit(treeRootHolder.getRoot());
}
LOG.warn("FILES MARKED AS UNCHANGED: " + fileUuidsMarkedAsUnchanged.size());
LOG.warn("FILES NOT MARKED AS UNCHANGED: " + notMarkedAsUnchanged);
}

private class Visitor extends TypeAwareVisitorAdapter {
@@ -68,8 +75,11 @@ public class FileStatusesImpl implements FileStatuses {
if (canTrustUnchangedFlags) {
if (file.getFileAttributes().isMarkedAsUnchanged()) {
fileUuidsMarkedAsUnchanged.add(file.getUuid());
} else {
notMarkedAsUnchanged++;
}
} else {
LOG.error("FILE HAS DIFFERENT HASH: " + file.getName());
fileUuidsMarkedAsUnchanged.clear();
}
}

+ 0
- 83
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/VariationSumFormula.java View File

@@ -1,83 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2022 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.component.CrawlerDepthLimit;
import org.sonar.ce.task.projectanalysis.formula.counter.DoubleValue;
import org.sonar.ce.task.projectanalysis.measure.Measure;

import static java.util.Objects.requireNonNull;
import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;

/**
* A Formula which aggregates variations of a specific metric by simply making the sums of its variations. It supports
* make the sum of only specific periods.
*/
public class VariationSumFormula implements Formula<VariationSumFormula.VariationSumCounter> {
private final String metricKey;

public VariationSumFormula(String metricKey) {
this.metricKey = requireNonNull(metricKey, "Metric key cannot be null");
}

@Override
public VariationSumCounter createNewCounter() {
return new VariationSumCounter(metricKey);
}

@Override
public Optional<Measure> createMeasure(VariationSumCounter counter, CreateMeasureContext context) {
if (!CrawlerDepthLimit.LEAVES.isDeeperThan(context.getComponent().getType()) || !counter.doubleValue.isSet()) {
return Optional.empty();
}
return Optional.of(newMeasureBuilder().setVariation(counter.doubleValue.getValue()).createNoValue());
}

@Override
public String[] getOutputMetricKeys() {
return new String[] {metricKey};
}

public static final class VariationSumCounter implements Counter<VariationSumCounter> {
private final DoubleValue doubleValue = new DoubleValue();
private final String metricKey;

private VariationSumCounter(String metricKey) {
this.metricKey = metricKey;
}

@Override
public void aggregate(VariationSumCounter counter) {
doubleValue.increment(counter.doubleValue);
}

@Override
public void initialize(CounterInitializationContext context) {
Optional<Measure> measure = context.getMeasure(metricKey);
if (!measure.isPresent() || !measure.get().hasVariation()) {
return;
}
double variation = measure.get().getVariation();
doubleValue.increment(variation);
}

}
}

+ 8
- 8
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/coverage/CoverageUtils.java View File

@@ -26,7 +26,8 @@ import org.sonar.ce.task.projectanalysis.measure.Measure;
import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;

public final class CoverageUtils {
private static final Measure DEFAULT_MEASURE = newMeasureBuilder().create(0L);
private static final Measure DEFAULT_MEASURE_LONG = newMeasureBuilder().create(0L);
private static final Measure DEFAULT_MEASURE_INT = newMeasureBuilder().create(0);

private CoverageUtils() {
// prevents instantiation
@@ -37,7 +38,7 @@ public final class CoverageUtils {
}

static long getLongMeasureValue(CounterInitializationContext counterContext, String metricKey) {
Measure measure = counterContext.getMeasure(metricKey).orElse(DEFAULT_MEASURE);
Measure measure = counterContext.getMeasure(metricKey).orElse(DEFAULT_MEASURE_LONG);
if (measure.getValueType() == Measure.ValueType.NO_VALUE) {
return 0L;
}
@@ -47,12 +48,11 @@ public final class CoverageUtils {
return measure.getLongValue();
}

static double getMeasureVariations(CounterInitializationContext counterContext, String metricKey) {
Optional<Measure> measure = counterContext.getMeasure(metricKey);
if (!measure.isPresent() || !measure.get().hasVariation()) {
return 0D;
static int getIntMeasureValue(CounterInitializationContext counterContext, String metricKey) {
Measure measure = counterContext.getMeasure(metricKey).orElse(DEFAULT_MEASURE_INT);
if (measure.getValueType() == Measure.ValueType.NO_VALUE) {
return 0;
}
return measure.get().getVariation();
return measure.getIntValue();
}

}

+ 0
- 48
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/coverage/CoverageVariationFormula.java View File

@@ -1,48 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2022 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.coverage;

import java.util.Optional;
import org.sonar.ce.task.projectanalysis.formula.CreateMeasureContext;
import org.sonar.ce.task.projectanalysis.formula.Formula;
import org.sonar.ce.task.projectanalysis.formula.counter.LongValue;
import org.sonar.ce.task.projectanalysis.measure.Measure;

import static org.sonar.ce.task.projectanalysis.formula.coverage.CoverageUtils.calculateCoverage;
import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;

/**
* An abstract Formula which implements the aggregation of a Counter of type ElementsAndCoveredElementsVariationCounter
* with another counter.
*/
public abstract class CoverageVariationFormula<T extends ElementsAndCoveredElementsVariationCounter> implements Formula<T> {

@Override
public Optional<Measure> createMeasure(T counter, CreateMeasureContext context) {
LongValue elements = counter.elements;
if (elements.isSet() && elements.getValue() > 0D) {
LongValue coveredElements = counter.coveredElements;
double variation = calculateCoverage(coveredElements.getValue(), elements.getValue());
return Optional.of(newMeasureBuilder().setVariation(variation).createNoValue());
}
return Optional.empty();
}

}

+ 0
- 49
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/coverage/ElementsAndCoveredElementsVariationCounter.java View File

@@ -1,49 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2022 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.coverage;

import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.ce.task.projectanalysis.formula.Counter;
import org.sonar.ce.task.projectanalysis.formula.CounterInitializationContext;
import org.sonar.ce.task.projectanalysis.formula.counter.LongValue;

/**
* A counter used to create measure variations which are based on a count of elements and coveredElements.
*/
public abstract class ElementsAndCoveredElementsVariationCounter implements Counter<ElementsAndCoveredElementsVariationCounter> {
protected final LongValue elements = new LongValue();
protected final LongValue coveredElements = new LongValue();

@Override
public void aggregate(ElementsAndCoveredElementsVariationCounter counter) {
elements.increment(counter.elements);
coveredElements.increment(counter.coveredElements);
}

@Override
public void initialize(CounterInitializationContext context) {
if (context.getLeaf().getType() == Component.Type.FILE && context.getLeaf().getFileAttributes().isUnitTest()) {
return;
}
initializeForSupportedLeaf(context);
}

protected abstract void initializeForSupportedLeaf(CounterInitializationContext counterContext);
}

+ 0
- 48
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/coverage/LinesAndConditionsWithUncoveredVariationCounter.java View File

@@ -1,48 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2022 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.coverage;

import java.util.Optional;
import org.sonar.ce.task.projectanalysis.formula.CounterInitializationContext;
import org.sonar.ce.task.projectanalysis.measure.Measure;

public final class LinesAndConditionsWithUncoveredVariationCounter extends ElementsAndCoveredElementsVariationCounter {
private final LinesAndConditionsWithUncoveredMetricKeys metricKeys;

public LinesAndConditionsWithUncoveredVariationCounter(LinesAndConditionsWithUncoveredMetricKeys metricKeys) {
this.metricKeys = metricKeys;
}

@Override
public void initializeForSupportedLeaf(CounterInitializationContext counterContext) {
Optional<Measure> newLinesMeasure = counterContext.getMeasure(metricKeys.getLines());
if (!newLinesMeasure.isPresent() || !newLinesMeasure.get().hasVariation()) {
return;
}
double newLines = newLinesMeasure.get().getVariation();
long newConditions = (long) CoverageUtils.getMeasureVariations(counterContext, metricKeys.getConditions());
long uncoveredLines = (long) CoverageUtils.getMeasureVariations(counterContext, metricKeys.getUncoveredLines());
long uncoveredConditions = (long) CoverageUtils.getMeasureVariations(counterContext, metricKeys.getUncoveredConditions());

long elements = (long) newLines + newConditions;
this.elements.increment(elements);
coveredElements.increment(elements - uncoveredConditions - uncoveredLines);
}
}

+ 0
- 46
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/coverage/LinesAndConditionsWithUncoveredVariationFormula.java View File

@@ -1,46 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2022 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.coverage;

import static java.util.Objects.requireNonNull;

/**
* A Formula which implements the aggregation the variations of lines and conditions measures (and their associated "uncovered" measures)
* into the variations of a fifth measure.
*/
public class LinesAndConditionsWithUncoveredVariationFormula extends CoverageVariationFormula<LinesAndConditionsWithUncoveredVariationCounter> {
private final LinesAndConditionsWithUncoveredMetricKeys inputKeys;
private final String outputKey;

public LinesAndConditionsWithUncoveredVariationFormula(LinesAndConditionsWithUncoveredMetricKeys inputKeys, String outputKey) {
this.inputKeys = requireNonNull(inputKeys);
this.outputKey = requireNonNull(outputKey);
}

@Override
public LinesAndConditionsWithUncoveredVariationCounter createNewCounter() {
return new LinesAndConditionsWithUncoveredVariationCounter(inputKeys);
}

@Override
public String[] getOutputMetricKeys() {
return new String[] {outputKey};
}
}

+ 0
- 41
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/coverage/SingleWithUncoveredVariationCounter.java View File

@@ -1,41 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2022 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.coverage;

import org.sonar.ce.task.projectanalysis.formula.CounterInitializationContext;

import static java.util.Objects.requireNonNull;
import static org.sonar.ce.task.projectanalysis.formula.coverage.CoverageUtils.getMeasureVariations;

public final class SingleWithUncoveredVariationCounter extends ElementsAndCoveredElementsVariationCounter {
private final SingleWithUncoveredMetricKeys metricKeys;

public SingleWithUncoveredVariationCounter(SingleWithUncoveredMetricKeys metricKeys) {
this.metricKeys = requireNonNull(metricKeys);
}

@Override
protected void initializeForSupportedLeaf(CounterInitializationContext counterContext) {
long newConditions = (long) getMeasureVariations(counterContext, metricKeys.getCovered());
long uncoveredConditions = (long) getMeasureVariations(counterContext, metricKeys.getUncovered());
this.elements.increment(newConditions);
coveredElements.increment(newConditions - uncoveredConditions);
}
}

+ 0
- 46
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/coverage/SingleWithUncoveredVariationFormula.java View File

@@ -1,46 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2022 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.coverage;

import static java.util.Objects.requireNonNull;

/**
* A Formula which implements the aggregation of the variations of a measure and its associated "uncovered" measure
* into the variations of a third measure.
*/
public class SingleWithUncoveredVariationFormula extends CoverageVariationFormula<SingleWithUncoveredVariationCounter> {
private final SingleWithUncoveredMetricKeys inputKeys;
private final String outputKey;

protected SingleWithUncoveredVariationFormula(SingleWithUncoveredMetricKeys inputKeys, String outputKey) {
this.inputKeys = requireNonNull(inputKeys);
this.outputKey = requireNonNull(outputKey);
}

@Override
public SingleWithUncoveredVariationCounter createNewCounter() {
return new SingleWithUncoveredVariationCounter(inputKeys);
}

@Override
public String[] getOutputMetricKeys() {
return new String[] {outputKey};
}
}

+ 4
- 7
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/IssueCounter.java View File

@@ -187,10 +187,9 @@ public class IssueCounter extends IssueVisitor {
if (!newIssueClassifier.isEnabled()) {
return;
}
double unresolvedVariations = currentCounters.counterForPeriod().unresolved;
int unresolved = currentCounters.counterForPeriod().unresolved;
measureRepository.add(component, metricRepository.getByKey(NEW_VIOLATIONS_KEY), Measure.newMeasureBuilder()
.setVariation(unresolvedVariations)
.createNoValue());
.create(unresolved));

for (Map.Entry<String, String> entry : SEVERITY_TO_NEW_METRIC_KEY.entrySet()) {
String severity = entry.getKey();
@@ -198,8 +197,7 @@ public class IssueCounter extends IssueVisitor {
Multiset<String> bag = currentCounters.counterForPeriod().severityBag;
Metric metric = metricRepository.getByKey(metricKey);
measureRepository.add(component, metric, Measure.newMeasureBuilder()
.setVariation(bag.count(severity))
.createNoValue());
.create(bag.count(severity)));
}

// waiting for Java 8 lambda in order to factor this loop with the previous one
@@ -210,8 +208,7 @@ public class IssueCounter extends IssueVisitor {
Multiset<RuleType> bag = currentCounters.counterForPeriod().typeBag;
Metric metric = metricRepository.getByKey(metricKey);
measureRepository.add(component, metric, Measure.newMeasureBuilder()
.setVariation(bag.count(type))
.createNoValue());
.create(bag.count(type)));
}
}


+ 6
- 6
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/NewEffortAggregator.java View File

@@ -90,8 +90,8 @@ public class NewEffortAggregator extends IssueVisitor {
}

private void computeMeasure(Component component, Metric metric, EffortSum effortSum) {
double variation = effortSum.isEmpty ? 0.0 : effortSum.newEffort;
measureRepository.add(component, metric, Measure.newMeasureBuilder().setVariation(variation).createNoValue());
long value = effortSum.isEmpty ? 0 : effortSum.newEffort;
measureRepository.add(component, metric, Measure.newMeasureBuilder().create(value));
}

private class NewEffortCounter {
@@ -135,19 +135,19 @@ public class NewEffortAggregator extends IssueVisitor {
}

private static class EffortSum {
private Double newEffort;
private Long newEffort;
private boolean isEmpty = true;

void add(long newEffort) {
double previous = MoreObjects.firstNonNull(this.newEffort, 0D);
long previous = MoreObjects.firstNonNull(this.newEffort, 0L);
this.newEffort = previous + newEffort;
isEmpty = false;
}

void add(EffortSum other) {
Double otherValue = other.newEffort;
Long otherValue = other.newEffort;
if (otherValue != null) {
add(otherValue.longValue());
add(otherValue);
}
}
}

+ 0
- 9
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/BestValueOptimization.java View File

@@ -58,18 +58,9 @@ public class BestValueOptimization implements Predicate<Measure> {
private boolean isBestValueOptimized(Measure measure) {
return measure.getData() == null
&& !measure.hasQualityGateStatus()
&& hasNoVariation(measure, metric.getBestValue())
&& (measure.getValueType() == NO_VALUE || isBestValue(measure, metric.getBestValue()));
}

private static boolean hasNoVariation(Measure measure, Double bestValue) {
return !measure.hasVariation() || isVariationEmptyOrBestValue(measure.getVariation(), bestValue);
}

private static boolean isVariationEmptyOrBestValue(double variation, Double bestValue) {
return compare(variation, 0D) == 0 || compare(variation, bestValue) == 0;
}

private static boolean isBestValue(Measure measure, Double bestValue) {
switch (measure.getValueType()) {
case BOOLEAN:

+ 28
- 38
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/LiveMeasureDtoToMeasure.java View File

@@ -39,82 +39,72 @@ public class LiveMeasureDtoToMeasure {
String data = measureDto.getDataAsString();
switch (metric.getType().getValueType()) {
case INT:
return toIntegerMeasure(measureDto, value, data);
return toIntegerMeasure(value, data);
case LONG:
return toLongMeasure(measureDto, value, data);
return toLongMeasure(value, data);
case DOUBLE:
return toDoubleMeasure(measureDto, value, data);
return toDoubleMeasure(value, data);
case BOOLEAN:
return toBooleanMeasure(measureDto, value, data);
return toBooleanMeasure(value, data);
case STRING:
return toStringMeasure(measureDto, data);
return toStringMeasure(data);
case LEVEL:
return toLevelMeasure(measureDto, data);
return toLevelMeasure(data);
case NO_VALUE:
return toNoValueMeasure(measureDto);
return toNoValueMeasure();
default:
throw new IllegalArgumentException("Unsupported Measure.ValueType " + metric.getType().getValueType());
}
}

private static Optional<Measure> toIntegerMeasure(LiveMeasureDto measureDto, @Nullable Double value, @Nullable String data) {
private static Optional<Measure> toIntegerMeasure(@Nullable Double value, @Nullable String data) {
if (value == null) {
return toNoValueMeasure(measureDto);
return toNoValueMeasure();
}
return of(setCommonProperties(Measure.newMeasureBuilder(), measureDto).create(value.intValue(), data));
return of(Measure.newMeasureBuilder().create(value.intValue(), data));
}

private static Optional<Measure> toLongMeasure(LiveMeasureDto measureDto, @Nullable Double value, @Nullable String data) {
private static Optional<Measure> toLongMeasure(@Nullable Double value, @Nullable String data) {
if (value == null) {
return toNoValueMeasure(measureDto);
return toNoValueMeasure();
}
return of(setCommonProperties(Measure.newMeasureBuilder(), measureDto).create(value.longValue(), data));
return of(Measure.newMeasureBuilder().create(value.longValue(), data));
}

private static Optional<Measure> toDoubleMeasure(LiveMeasureDto measureDto, @Nullable Double value, @Nullable String data) {
private static Optional<Measure> toDoubleMeasure(@Nullable Double value, @Nullable String data) {
if (value == null) {
return toNoValueMeasure(measureDto);
return toNoValueMeasure();
}

return of(setCommonProperties(Measure.newMeasureBuilder(), measureDto)
.create(value, org.sonar.api.measures.Metric.MAX_DECIMAL_SCALE, data));
return of(Measure.newMeasureBuilder().create(value, org.sonar.api.measures.Metric.MAX_DECIMAL_SCALE, data));
}

private static Optional<Measure> toBooleanMeasure(LiveMeasureDto measureDto, @Nullable Double value, @Nullable String data) {
private static Optional<Measure> toBooleanMeasure(@Nullable Double value, @Nullable String data) {
if (value == null) {
return toNoValueMeasure(measureDto);
return toNoValueMeasure();
}
return of(setCommonProperties(Measure.newMeasureBuilder(), measureDto).create(Double.compare(value, 1.0D) == 0, data));
return of(Measure.newMeasureBuilder().create(Double.compare(value, 1.0D) == 0, data));
}

private static Optional<Measure> toStringMeasure(LiveMeasureDto measureDto, @Nullable String data) {
private static Optional<Measure> toStringMeasure(@Nullable String data) {
if (data == null) {
return toNoValueMeasure(measureDto);
return toNoValueMeasure();
}
return of(setCommonProperties(Measure.newMeasureBuilder(), measureDto).create(data));
return of(Measure.newMeasureBuilder().create(data));
}

private static Optional<Measure> toLevelMeasure(LiveMeasureDto measureDto, @Nullable String data) {
private static Optional<Measure> toLevelMeasure(@Nullable String data) {
if (data == null) {
return toNoValueMeasure(measureDto);
return toNoValueMeasure();
}
Optional<Measure.Level> level = toLevel(data);
if (!level.isPresent()) {
return toNoValueMeasure(measureDto);
return toNoValueMeasure();
}
return of(setCommonProperties(Measure.newMeasureBuilder(), measureDto).create(level.get()));
return of(Measure.newMeasureBuilder().create(level.get()));
}

private static Optional<Measure> toNoValueMeasure(LiveMeasureDto measureDto) {
return of(setCommonProperties(Measure.newMeasureBuilder(), measureDto).createNoValue());
private static Optional<Measure> toNoValueMeasure() {
return of(Measure.newMeasureBuilder().createNoValue());
}

private static Measure.NewMeasureBuilder setCommonProperties(Measure.NewMeasureBuilder builder, LiveMeasureDto measureDto) {
Double variation = measureDto.getVariation();
if (variation != null) {
builder.setVariation(variation);
}
return builder;
}

}

+ 18
- 97
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/Measure.java View File

@@ -28,6 +28,7 @@ import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
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;
@@ -139,20 +140,8 @@ public interface Measure {
*/
QualityGateStatus getQualityGateStatus();

/**
* Any Measure, which ever is its value type, can have a variation.
*/
boolean hasVariation();

/**
* The variation of this measure.
*
* @throws IllegalStateException if the measure has no variation
*/
double getVariation();

default boolean isEmpty() {
return getValueType() == ValueType.NO_VALUE && !hasVariation() && getData() == null;
return getValueType() == ValueType.NO_VALUE && getData() == null;
}

static NewMeasureBuilder newMeasureBuilder() {
@@ -173,17 +162,13 @@ public interface Measure {
private final Level dataLevel;
@CheckForNull
private final QualityGateStatus qualityGateStatus;
@CheckForNull
private final Double variation;

private MeasureImpl(ValueType valueType, @Nullable Double value, @Nullable String data, @Nullable Level dataLevel,
@Nullable QualityGateStatus qualityGateStatus, @Nullable Double variation) {
private MeasureImpl(ValueType valueType, @Nullable Double value, @Nullable String data, @Nullable Level dataLevel, @Nullable QualityGateStatus qualityGateStatus) {
this.valueType = valueType;
this.value = DoubleCache.intern(value);
this.data = data;
this.dataLevel = dataLevel;
this.qualityGateStatus = qualityGateStatus;
this.variation = variation;
}

@Override
@@ -243,17 +228,6 @@ public interface Measure {
return this.qualityGateStatus;
}

@Override
public boolean hasVariation() {
return variation != null;
}

@Override
public double getVariation() {
checkState(variation != null, "Measure does not have variation");
return variation;
}

private static void checkValueType(ValueType expected, ValueType valueType) {
if (valueType != expected) {
throw new IllegalStateException(
@@ -266,13 +240,12 @@ public interface Measure {

@Override
public String toString() {
return com.google.common.base.MoreObjects.toStringHelper(this)
return toStringHelper(this)
.add("valueType", valueType)
.add("value", value)
.add("data", data)
.add("dataLevel", dataLevel)
.add("qualityGateStatus", qualityGateStatus)
.add("variations", variation)
.toString();
}
}
@@ -341,16 +314,6 @@ public interface Measure {
throw new IllegalStateException("Measure does not have an QualityGate status");
}

@Override
public boolean hasVariation() {
return false;
}

@Override
public double getVariation() {
throw new IllegalStateException("Measure does not have variation");
}

@Override
public boolean equals(Object o) {
if (this == o)
@@ -368,21 +331,14 @@ public interface Measure {

@Override
public String toString() {
return com.google.common.base.MoreObjects.toStringHelper(this)
return toStringHelper(this)
.add("valueType", valueType)
.add("value", value)
.toString();
}
}

class NoValueVariationMeasureImpl implements Measure {
@Nullable
private Double variation;

private NoValueVariationMeasureImpl(@Nullable Double variation) {
this.variation = variation;
}

class NoValueMeasureImpl implements Measure {
@Override
public ValueType getValueType() {
return ValueType.NO_VALUE;
@@ -416,7 +372,6 @@ public interface Measure {
@Override
public Level getLevelValue() {
throw new IllegalStateException();

}

@Override
@@ -434,40 +389,22 @@ public interface Measure {
throw new IllegalStateException("Measure does not have an QualityGate status");
}

@Override
public boolean hasVariation() {
return variation != null;
}

@Override
public double getVariation() {
checkState(variation != null, "Measure does not have variation");
return variation;
}

@Override
public String toString() {
return com.google.common.base.MoreObjects.toStringHelper(this)
return toStringHelper(this)
.add("valueType", ValueType.NO_VALUE)
.add("variations", variation)
.toString();
}
}

class NewMeasureBuilder {
private QualityGateStatus qualityGateStatus;
private Double variation;

public NewMeasureBuilder setQualityGateStatus(QualityGateStatus qualityGateStatus) {
this.qualityGateStatus = requireNonNull(qualityGateStatus, "QualityGateStatus can not be set to null");
return this;
}

public NewMeasureBuilder setVariation(double variation) {
this.variation = variation;
return this;
}

public Measure create(boolean value, @Nullable String data) {
return createInternal(ValueType.BOOLEAN, value ? 1.0D : 0.0D, data);
}
@@ -499,30 +436,34 @@ public interface Measure {
}

private Measure createInternal(ValueType type, double value, @Nullable String data) {
if (data == null && qualityGateStatus == null && variation == null) {
if (data == null && qualityGateStatus == null) {
return new ValueMeasureImpl(type, value);

}
return new MeasureImpl(type, value, data, null, qualityGateStatus, variation);
return new MeasureImpl(type, value, data, null, qualityGateStatus);
}

public Measure create(double value, int decimalScale) {
return create(value, decimalScale, null);
}

public Measure create(double value) {
return create(value, org.sonar.api.measures.Metric.MAX_DECIMAL_SCALE);
}

public Measure create(String value) {
return new MeasureImpl(ValueType.STRING, null, requireNonNull(value), null, qualityGateStatus, variation);
return new MeasureImpl(ValueType.STRING, null, requireNonNull(value), null, qualityGateStatus);
}

public Measure create(Level level) {
return new MeasureImpl(ValueType.LEVEL, null, null, requireNonNull(level), qualityGateStatus, variation);
return new MeasureImpl(ValueType.LEVEL, null, null, requireNonNull(level), qualityGateStatus);
}

public Measure createNoValue() {
if (qualityGateStatus == null) {
return new NoValueVariationMeasureImpl(variation);
return new NoValueMeasureImpl();
}
return new MeasureImpl(ValueType.NO_VALUE, null, null, null, qualityGateStatus, variation);
return new MeasureImpl(ValueType.NO_VALUE, null, null, null, qualityGateStatus);
}

private static double scale(double value, int decimalScale) {
@@ -534,7 +475,6 @@ public interface Measure {
final class UpdateMeasureBuilder {
private final Measure source;
private QualityGateStatus qualityGateStatus;
private Double variation;

public UpdateMeasureBuilder(Measure source) {
this.source = requireNonNull(source, "Can not create a measure from null");
@@ -554,19 +494,6 @@ public interface Measure {
return this;
}

/**
* Sets the variation of the updated Measure to create.
*
* @throws UnsupportedOperationException if the source measure already has a variation
*/
public UpdateMeasureBuilder setVariation(double variation) {
if (source.hasVariation()) {
throw new UnsupportedOperationException("Variation can not be changed if already set on source Measure");
}
this.variation = variation;
return this;
}

public Measure create() {
Double value;
switch (source.getValueType()) {
@@ -589,13 +516,7 @@ public interface Measure {
}
Level level = source.getValueType() == ValueType.LEVEL ? source.getLevelValue() : null;
QualityGateStatus status = source.hasQualityGateStatus() ? source.getQualityGateStatus() : qualityGateStatus;
Double var;
if (source.hasVariation()) {
var = source.getVariation();
} else {
var = variation;
}
return new MeasureImpl(source.getValueType(), value, source.getData(), level, status, var);
return new MeasureImpl(source.getValueType(), value, source.getData(), level, status);
}
}
}

+ 0
- 8
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/MeasureDtoToMeasure.java View File

@@ -116,14 +116,6 @@ public class MeasureDtoToMeasure {
builder.setQualityGateStatus(new QualityGateStatus(qualityGateStatus.get(), measureDto.getAlertText()));
}
}
if (hasAnyVariation(measureDto)) {
builder.setVariation(measureDto.getVariation());
}
return builder;
}

private static boolean hasAnyVariation(MeasureDto measureDto) {
return measureDto.getVariation() != null;
}

}

+ 0
- 6
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/MeasureToMeasureDto.java View File

@@ -42,9 +42,6 @@ public class MeasureToMeasureDto {
out.setMetricUuid(metric.getUuid());
out.setComponentUuid(component.getUuid());
out.setAnalysisUuid(analysisMetadataHolder.getUuid());
if (measure.hasVariation()) {
out.setVariation(measure.getVariation());
}
if (measure.hasQualityGateStatus()) {
setAlert(out, measure.getQualityGateStatus());
}
@@ -58,9 +55,6 @@ public class MeasureToMeasureDto {
out.setMetricUuid(metric.getUuid());
out.setComponentUuid(component.getUuid());
out.setProjectUuid(treeRootHolder.getRoot().getUuid());
if (measure.hasVariation()) {
out.setVariation(measure.getVariation());
}
out.setValue(valueAsDouble(measure));
out.setData(data(measure));
return out;

+ 2
- 27
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitygate/ConditionEvaluator.java View File

@@ -45,7 +45,7 @@ public final class ConditionEvaluator {
public EvaluationResult evaluate(Condition condition, Measure measure) {
checkArgument(SUPPORTED_METRIC_TYPE.contains(condition.getMetric().getType()), "Conditions on MetricType %s are not supported", condition.getMetric().getType());

Comparable measureComparable = parseMeasure(condition, measure);
Comparable measureComparable = parseMeasure(measure);
if (measureComparable == null) {
return new EvaluationResult(Measure.Level.OK, null);
}
@@ -100,10 +100,7 @@ public final class ConditionEvaluator {
}

@CheckForNull
private static Comparable parseMeasure(Condition condition, Measure measure) {
if (condition.useVariation()) {
return parseMeasureFromVariation(condition, measure);
}
private static Comparable parseMeasure(Measure measure) {
switch (measure.getValueType()) {
case INT:
return measure.getIntValue();
@@ -120,26 +117,4 @@ public final class ConditionEvaluator {
String.format("Unsupported measure ValueType %s. Can not parse measure to a Comparable", measure.getValueType()));
}
}

@CheckForNull
private static Comparable parseMeasureFromVariation(Condition condition, Measure measure) {
if (!measure.hasVariation()) {
return null;
}

Double variation = measure.getVariation();
Metric.MetricType metricType = condition.getMetric().getType();
switch (metricType.getValueType()) {
case INT:
return variation.intValue();
case LONG:
return variation.longValue();
case DOUBLE:
return variation;
case NO_VALUE:
case LEVEL:
default:
throw new IllegalArgumentException("Unsupported metric type " + metricType);
}
}
}

+ 6
- 9
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewMaintainabilityMeasuresVisitor.java View File

@@ -110,11 +110,11 @@ public class NewMaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<N
}
double density = computeDensity(path.current());
double newDebtRatio = 100.0 * density;
double newMaintainability = ratingSettings.getDebtRatingGrid().getRatingForDensity(density).getIndex();
long newDevelopmentCost = path.current().getDevCost().getValue();
measureRepository.add(component, this.newDevelopmentCostMetric, newMeasureBuilder().setVariation(newDevelopmentCost).createNoValue());
measureRepository.add(component, this.newDebtRatioMetric, newMeasureBuilder().setVariation(newDebtRatio).createNoValue());
measureRepository.add(component, this.newMaintainabilityRatingMetric, newMeasureBuilder().setVariation(newMaintainability).createNoValue());
int newMaintainability = ratingSettings.getDebtRatingGrid().getRatingForDensity(density).getIndex();
float newDevelopmentCost = path.current().getDevCost().getValue();
measureRepository.add(component, this.newDevelopmentCostMetric, newMeasureBuilder().create(newDevelopmentCost));
measureRepository.add(component, this.newDebtRatioMetric, newMeasureBuilder().create(newDebtRatio));
measureRepository.add(component, this.newMaintainabilityRatingMetric, newMeasureBuilder().create(newMaintainability));
}

private static double computeDensity(Counter counter) {
@@ -133,10 +133,7 @@ public class NewMaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<N
}

private static long getLongValue(Measure measure) {
if (measure.hasVariation()) {
return (long) measure.getVariation();
}
return 0L;
return measure.getLongValue();
}

private void initNewDebtRatioCounter(Component file, Path<Counter> path) {

+ 1
- 1
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewReliabilityAndSecurityRatingMeasuresVisitor.java View File

@@ -112,7 +112,7 @@ public class NewReliabilityAndSecurityRatingMeasuresVisitor extends PathAwareVis
entry -> measureRepository.add(
component,
metricsByKey.get(entry.getKey()),
newMeasureBuilder().setVariation(entry.getValue().getValue().getIndex()).createNoValue()));
newMeasureBuilder().create(entry.getValue().getValue().getIndex())));
addToParent(path);
}


+ 4
- 4
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewSecurityReviewMeasuresVisitor.java View File

@@ -69,8 +69,8 @@ public class NewSecurityReviewMeasuresVisitor extends PathAwareVisitorAdapter<Se
computeMeasure(project, path);

// The following measures are only computed on projects level as they are required to compute the others measures on applications
measureRepository.add(project, newSecurityHotspotsReviewedStatusMetric, Measure.newMeasureBuilder().setVariation(path.current().getHotspotsReviewed()).createNoValue());
measureRepository.add(project, newSecurityHotspotsToReviewStatusMetric, Measure.newMeasureBuilder().setVariation(path.current().getHotspotsToReview()).createNoValue());
measureRepository.add(project, newSecurityHotspotsReviewedStatusMetric, Measure.newMeasureBuilder().create(path.current().getHotspotsReviewed()));
measureRepository.add(project, newSecurityHotspotsToReviewStatusMetric, Measure.newMeasureBuilder().create(path.current().getHotspotsToReview()));
}

@Override
@@ -91,8 +91,8 @@ public class NewSecurityReviewMeasuresVisitor extends PathAwareVisitorAdapter<Se
.forEach(issue -> path.current().processHotspot(issue));

Optional<Double> percent = computePercent(path.current().getHotspotsToReview(), path.current().getHotspotsReviewed());
measureRepository.add(component, newSecurityReviewRatingMetric, Measure.newMeasureBuilder().setVariation(computeRating(percent.orElse(null)).getIndex()).createNoValue());
percent.ifPresent(p -> measureRepository.add(component, newSecurityHotspotsReviewedMetric, Measure.newMeasureBuilder().setVariation(p).createNoValue()));
measureRepository.add(component, newSecurityReviewRatingMetric, Measure.newMeasureBuilder().create(computeRating(percent.orElse(null)).getIndex()));
percent.ifPresent(p -> measureRepository.add(component, newSecurityHotspotsReviewedMetric, Measure.newMeasureBuilder().create(p)));

if (!path.isRoot()) {
path.parent().add(path.current());

+ 7
- 7
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/NewCoverageMeasuresStep.java View File

@@ -35,10 +35,10 @@ import org.sonar.ce.task.projectanalysis.formula.CreateMeasureContext;
import org.sonar.ce.task.projectanalysis.formula.Formula;
import org.sonar.ce.task.projectanalysis.formula.FormulaExecutorComponentVisitor;
import org.sonar.ce.task.projectanalysis.formula.counter.IntValue;
import org.sonar.ce.task.projectanalysis.formula.coverage.LinesAndConditionsWithUncoveredFormula;
import org.sonar.ce.task.projectanalysis.formula.coverage.LinesAndConditionsWithUncoveredMetricKeys;
import org.sonar.ce.task.projectanalysis.formula.coverage.LinesAndConditionsWithUncoveredVariationFormula;
import org.sonar.ce.task.projectanalysis.formula.coverage.SingleWithUncoveredFormula;
import org.sonar.ce.task.projectanalysis.formula.coverage.SingleWithUncoveredMetricKeys;
import org.sonar.ce.task.projectanalysis.formula.coverage.SingleWithUncoveredVariationFormula;
import org.sonar.ce.task.projectanalysis.measure.Measure;
import org.sonar.ce.task.projectanalysis.measure.MeasureRepository;
import org.sonar.ce.task.projectanalysis.metric.Metric;
@@ -56,7 +56,7 @@ import static org.sonar.api.measures.CoreMetrics.NEW_UNCOVERED_LINES_KEY;
import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;

/**
* Computes measures related to the New Coverage. These measures do not have values, only variations.
* Computes measures related to the New Coverage.
*/
public class NewCoverageMeasuresStep implements ComputationStep {
private static final List<Formula<?>> FORMULAS = List.of(
@@ -95,7 +95,7 @@ public class NewCoverageMeasuresStep implements ComputationStep {
return "Compute new coverage";
}

private static class NewCoverageFormula extends LinesAndConditionsWithUncoveredVariationFormula {
private static class NewCoverageFormula extends LinesAndConditionsWithUncoveredFormula {
NewCoverageFormula() {
super(
new LinesAndConditionsWithUncoveredMetricKeys(
@@ -105,7 +105,7 @@ public class NewCoverageMeasuresStep implements ComputationStep {
}
}

private static class NewBranchCoverageFormula extends SingleWithUncoveredVariationFormula {
private static class NewBranchCoverageFormula extends SingleWithUncoveredFormula {
NewBranchCoverageFormula() {
super(
new SingleWithUncoveredMetricKeys(NEW_CONDITIONS_TO_COVER_KEY, NEW_UNCOVERED_CONDITIONS_KEY),
@@ -113,7 +113,7 @@ public class NewCoverageMeasuresStep implements ComputationStep {
}
}

private static class NewLineCoverageFormula extends SingleWithUncoveredVariationFormula {
private static class NewLineCoverageFormula extends SingleWithUncoveredFormula {
NewLineCoverageFormula() {
super(
new SingleWithUncoveredMetricKeys(NEW_LINES_TO_COVER_KEY, NEW_UNCOVERED_LINES_KEY),
@@ -143,7 +143,7 @@ public class NewCoverageMeasuresStep implements ComputationStep {
public Optional<Measure> createMeasure(NewCoverageCounter counter, CreateMeasureContext context) {
if (counter.hasNewCode()) {
int value = computeValueForMetric(counter, context.getMetric());
return Optional.of(newMeasureBuilder().setVariation(value).createNoValue());
return Optional.of(newMeasureBuilder().create(value));
}
return Optional.empty();
}

+ 6
- 6
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/NewSizeMeasuresStep.java View File

@@ -205,7 +205,7 @@ public class NewSizeMeasuresStep implements ComputationStep {

private static Optional<Measure> createMeasure(IntValue intValue) {
return intValue.isSet()
? Optional.of(Measure.newMeasureBuilder().setVariation(intValue.getValue()).createNoValue())
? Optional.of(Measure.newMeasureBuilder().create(intValue.getValue()))
: Optional.empty();
}

@@ -213,11 +213,11 @@ public class NewSizeMeasuresStep implements ComputationStep {
IntValue newLines = counter.newLines;
IntValue newDuplicatedLines = counter.newDuplicatedLines;
if (newLines.isSet() && newDuplicatedLines.isSet()) {
int newLinesVariations = newLines.getValue();
int newDuplicatedLinesVariations = newDuplicatedLines.getValue();
if (newLinesVariations > 0D) {
double density = Math.min(100D, 100D * newDuplicatedLinesVariations / newLinesVariations);
return Optional.of(Measure.newMeasureBuilder().setVariation(density).createNoValue());
int newLinesValue = newLines.getValue();
int newDuplicatedLinesValue = newDuplicatedLines.getValue();
if (newLinesValue > 0D) {
double density = Math.min(100D, 100D * newDuplicatedLinesValue / newLinesValue);
return Optional.of(Measure.newMeasureBuilder().create(density));
}
}
return Optional.empty();

+ 1
- 1
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistLiveMeasuresStep.java View File

@@ -217,7 +217,7 @@ public class PersistLiveMeasuresStep implements ComputationStep {

@Override
public boolean test(@Nonnull Measure input) {
return input.getValueType() != Measure.ValueType.NO_VALUE || input.hasVariation() || input.getData() != null;
return input.getValueType() != Measure.ValueType.NO_VALUE || input.getData() != null;
}
}
}

+ 1
- 1
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/SmallChangesetQualityGateSpecialCase.java View File

@@ -59,7 +59,7 @@ public class SmallChangesetQualityGateSpecialCase {

private boolean isSmallChangeset(Component project) {
return measureRepository.getRawMeasure(project, metricRepository.getByKey(CoreMetrics.NEW_LINES_KEY))
.map(newLines -> newLines.hasVariation() && newLines.getVariation() < MAXIMUM_NEW_LINES_FOR_SMALL_CHANGESETS)
.map(newLines -> newLines.getIntValue() < MAXIMUM_NEW_LINES_FOR_SMALL_CHANGESETS)
.orElse(false);
}
}

+ 8
- 7
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectexport/steps/ExportLiveMeasuresStep.java View File

@@ -36,7 +36,7 @@ import static org.sonar.db.DatabaseUtils.getString;

public class ExportLiveMeasuresStep implements ComputationStep {

private static final String QUERY = "select pm.metric_uuid, pm.component_uuid, pm.text_value, pm.value, pm.variation" +
private static final String QUERY = "select pm.metric_uuid, pm.component_uuid, pm.text_value, pm.value, m.name" +
" from live_measures pm" +
" join metrics m on m.uuid=pm.metric_uuid" +
" join components p on p.uuid = pm.component_uuid" +
@@ -95,12 +95,13 @@ public class ExportLiveMeasuresStep implements ComputationStep {
.setComponentRef(componentRef)
.setTextValue(defaultString(getString(rs, 3)));
Double value = getDouble(rs, 4);
if (value != null) {
builder.setDoubleValue(doubleBuilder.setValue(value).build());
}
Double variation = getDouble(rs, 5);
if (variation != null) {
builder.setVariation(doubleBuilder.setValue(variation).build());
String metricKey = getString(rs, 5);
if (value != null && metricKey != null) {
if (metricKey.startsWith("new_")) {
builder.setVariation(doubleBuilder.setValue(value).build());
} else {
builder.setDoubleValue(doubleBuilder.setValue(value).build());
}
}
return builder.build();
}

+ 8
- 6
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectexport/steps/ExportMeasuresStep.java View File

@@ -39,7 +39,7 @@ import static org.sonar.db.DatabaseUtils.getString;
public class ExportMeasuresStep implements ComputationStep {

private static final String QUERY = "select pm.metric_uuid, pm.analysis_uuid, pm.component_uuid, pm.text_value, pm.value," +
" pm.alert_status, pm.alert_text, pm.variation_value_1" +
" pm.alert_status, pm.alert_text, m.name" +
" from project_measures pm" +
" join metrics m on m.uuid=pm.metric_uuid" +
" join snapshots s on s.uuid=pm.analysis_uuid" +
@@ -104,6 +104,7 @@ public class ExportMeasuresStep implements ComputationStep {
ProjectDump.DoubleValue.Builder doubleBuilder) throws SQLException {
long componentRef = componentRepository.getRef(rs.getString(3));
int metricRef = metricHolder.add(rs.getString(1));
String metricKey = rs.getString(8);

builder
.clear()
@@ -112,15 +113,16 @@ public class ExportMeasuresStep implements ComputationStep {
.setComponentRef(componentRef)
.setTextValue(defaultString(getString(rs, 4)));
Double value = getDouble(rs, 5);

if (value != null) {
builder.setDoubleValue(doubleBuilder.setValue(value).build());
if (metricKey.startsWith("new_")) {
builder.setVariation1(doubleBuilder.setValue(value).build());
} else {
builder.setDoubleValue(doubleBuilder.setValue(value).build());
}
}
builder.setAlertStatus(defaultString(getString(rs, 6)));
builder.setAlertText(defaultString(getString(rs, 7)));
Double var1 = getDouble(rs, 8);
if (var1 != null) {
builder.setVariation1(doubleBuilder.setValue(var1).build());
}
return builder.build();
}


+ 7
- 87
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/ReportFormulaExecutorComponentVisitorTest.java View File

@@ -28,7 +28,6 @@ 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.formula.counter.IntValue;
import org.sonar.ce.task.projectanalysis.measure.Measure;
import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
import org.sonar.ce.task.projectanalysis.metric.Metric;
@@ -129,25 +128,6 @@ public class ReportFormulaExecutorComponentVisitorTest {
entryOf(NEW_COVERAGE_KEY, newMeasureBuilder().create(102)));
}

@Test
public void verify_aggregation_on_variation() {
treeRootHolder.setRoot(BALANCED_COMPONENT_TREE);

measureRepository.addRawMeasure(FILE_1_REF, NEW_LINES_TO_COVER_KEY, createMeasureWithVariation(10));
measureRepository.addRawMeasure(FILE_2_REF, NEW_LINES_TO_COVER_KEY, createMeasureWithVariation(8));
measureRepository.addRawMeasure(FILE_3_REF, NEW_LINES_TO_COVER_KEY, createMeasureWithVariation(2));

new PathAwareCrawler<>(formulaExecutorComponentVisitor(new FakeVariationFormula()))
.visit(BALANCED_COMPONENT_TREE);

assertAddedRawMeasureVariation(ROOT_REF, 20);
assertAddedRawMeasureVariation(DIRECTORY_1_REF, 18);
assertAddedRawMeasureVariation(FILE_1_REF, 10);
assertAddedRawMeasureVariation(FILE_2_REF, 8);
assertAddedRawMeasureVariation(DIRECTORY_2_REF, 2);
assertAddedRawMeasureVariation(FILE_3_REF, 2);
}

@Test
public void measures_are_0_when_there_is_no_input_measure() {
ReportComponent project = ReportComponent.builder(PROJECT, ROOT_REF)
@@ -219,13 +199,13 @@ public class ReportFormulaExecutorComponentVisitorTest {
treeRootHolder.setRoot(root);
measureRepository.addRawMeasure(FILE_1_REF, NCLOC_KEY, newMeasureBuilder().create(2));

// expectedException.expectCause(
// hasType(UnsupportedOperationException.class)
// .andMessage(String.format("A measure can only be set once for Component (ref=%s), Metric (key=%s)", FILE_1_REF, NCLOC_KEY))
// );
// expectedException.expectCause(
// hasType(UnsupportedOperationException.class)
// .andMessage(String.format("A measure can only be set once for Component (ref=%s), Metric (key=%s)", FILE_1_REF, NCLOC_KEY))
// );

assertThatThrownBy(() -> new PathAwareCrawler<>(formulaExecutorComponentVisitor(new FakeFormula())).visit(root))
.hasCause( new UnsupportedOperationException(String.format("A measure can only be set once for Component (ref=%s), Metric (key=%s)", FILE_1_REF, NCLOC_KEY)));
.hasCause(new UnsupportedOperationException(String.format("A measure can only be set once for Component (ref=%s), Metric (key=%s)", FILE_1_REF, NCLOC_KEY)));
}

@Test
@@ -234,8 +214,8 @@ public class ReportFormulaExecutorComponentVisitorTest {
treeRootHolder.setRoot(root);
measureRepository.addRawMeasure(ROOT_REF, NCLOC_KEY, newMeasureBuilder().create(10));

// expectedException.expectCause(hasType(UnsupportedOperationException.class)
// .andMessage(String.format("A measure can only be set once for Component (ref=%s), Metric (key=%s)", ROOT_REF, NCLOC_KEY)));
// expectedException.expectCause(hasType(UnsupportedOperationException.class)
// .andMessage(String.format("A measure can only be set once for Component (ref=%s), Metric (key=%s)", ROOT_REF, NCLOC_KEY)));

assertThatThrownBy(() -> {
new PathAwareCrawler<>(formulaExecutorComponentVisitor(new FakeFormula()))
@@ -249,19 +229,10 @@ public class ReportFormulaExecutorComponentVisitorTest {
.buildFor(ImmutableList.of(formula));
}

private static Measure createMeasureWithVariation(double variation) {
return newMeasureBuilder().setVariation(variation).createNoValue();
}

private void assertAddedRawMeasure(int componentRef, int expectedValue) {
assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).containsOnly(entryOf(NCLOC_KEY, newMeasureBuilder().create(expectedValue)));
}

private void assertAddedRawMeasureVariation(int componentRef, int variation) {
assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef)))
.containsOnly(entryOf(NEW_COVERAGE_KEY, createMeasureWithVariation(variation)));
}

private class FakeFormula implements Formula<FakeCounter> {

@Override
@@ -336,55 +307,4 @@ public class ReportFormulaExecutorComponentVisitorTest {
}
}
}

private class FakeVariationFormula implements Formula<FakeVariationCounter> {

@Override
public FakeVariationCounter createNewCounter() {
return new FakeVariationCounter();
}

@Override
public Optional<Measure> createMeasure(FakeVariationCounter counter, CreateMeasureContext context) {
// verify the context which is passed to the method
assertThat(context.getComponent()).isNotNull();
assertThat(context.getMetric()).isSameAs(metricRepository.getByKey(NEW_COVERAGE_KEY));

IntValue measureVariations = counter.values;
if (measureVariations.isSet()) {
return Optional.of(
newMeasureBuilder()
.setVariation(measureVariations.getValue())
.createNoValue());
}
return Optional.empty();
}

@Override
public String[] getOutputMetricKeys() {
return new String[] {NEW_COVERAGE_KEY};
}
}

private static class FakeVariationCounter implements Counter<FakeVariationCounter> {
private final IntValue values = new IntValue();

@Override
public void aggregate(FakeVariationCounter counter) {
values.increment(counter.values);
}

@Override
public void initialize(CounterInitializationContext context) {
// verify the context which is passed to the method
assertThat(context.getLeaf().getChildren()).isEmpty();

Optional<Measure> measureOptional = context.getMeasure(NEW_LINES_TO_COVER_KEY);
if (!measureOptional.isPresent()) {
return;
}
this.values.increment((int) measureOptional.get().getVariation());
}
}

}

+ 2
- 37
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/ViewsFormulaExecutorComponentVisitorTest.java View File

@@ -124,38 +124,6 @@ public class ViewsFormulaExecutorComponentVisitorTest {
verifyMultiMetricValues(ROOT_REF, 22, 112);
}

@Test
public void verify_aggregation_on_variations() {
treeRootHolder.setRoot(BALANCED_COMPONENT_TREE);

addRawMeasureWithVariation(PROJECT_VIEW_1_REF, NEW_LINES_TO_COVER_KEY, 10);
addRawMeasureWithVariation(PROJECT_VIEW_2_REF, NEW_LINES_TO_COVER_KEY, 8);
addRawMeasureWithVariation(PROJECT_VIEW_3_REF, NEW_LINES_TO_COVER_KEY, 2);
addRawMeasureWithVariation(PROJECT_VIEW_4_REF, NEW_LINES_TO_COVER_KEY, 3);

new PathAwareCrawler<>(formulaExecutorComponentVisitor(new FakeVariationFormula()))
.visit(BALANCED_COMPONENT_TREE);

verifyProjectViewsHasNoAddedRawMeasures();
verifySingleMetricWithVariation(SUB_SUBVIEW_REF, 18);
verifySingleMetricWithVariation(SUBVIEW_1_REF, 18);
verifySingleMetricWithVariation(SUBVIEW_2_REF, 2);
verifySingleMetricWithVariation(ROOT_REF, 23);
}

private void verifySingleMetricWithVariation(int componentRef, int variation) {
assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef)))
.containsOnly(entryOf(NEW_COVERAGE_KEY, createMeasureWithVariation(variation)));
}

private MeasureRepositoryRule addRawMeasureWithVariation(int componentRef, String metricKey, int variation) {
return measureRepository.addRawMeasure(componentRef, metricKey, createMeasureWithVariation(variation));
}

private static Measure createMeasureWithVariation(double variation) {
return newMeasureBuilder().setVariation(variation).createNoValue();
}

@Test
public void verify_no_measure_added_on_projectView() {
ViewsComponent project = ViewsComponent.builder(VIEW, ROOT_REF)
@@ -287,10 +255,7 @@ public class ViewsFormulaExecutorComponentVisitorTest {

IntValue measureVariations = counter.values;
if (measureVariations.isSet()) {
return Optional.of(
newMeasureBuilder()
.setVariation(measureVariations.getValue())
.createNoValue());
return Optional.of(newMeasureBuilder().create(measureVariations.getValue()));
}
return Optional.empty();
}
@@ -317,7 +282,7 @@ public class ViewsFormulaExecutorComponentVisitorTest {
if (!measureOptional.isPresent()) {
return;
}
this.values.increment((int) measureOptional.get().getVariation());
this.values.increment(measureOptional.get().getIntValue());
}

}

+ 20
- 20
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/counter/IntValueTest.java View File

@@ -25,58 +25,58 @@ import static org.assertj.core.api.Assertions.assertThat;

public class IntValueTest {
@Test
public void newly_created_IntVariationValue_is_unset_and_has_value_0() {
verifyUnsetVariationValue(new IntValue());
public void newly_created_IntValue_is_unset_and_has_value_0() {
verifyUnsetValue(new IntValue());
}

@Test
public void increment_int_sets_IntVariationValue_and_increments_value() {
verifySetVariationValue(new IntValue().increment(10), 10);
public void increment_int_sets_IntValue_and_increments_value() {
verifySetValue(new IntValue().increment(10), 10);
}

@Test
public void increment_IntVariationValue_has_no_effect_if_arg_is_null() {
verifyUnsetVariationValue(new IntValue().increment(null));
public void increment_IntValue_has_no_effect_if_arg_is_null() {
verifyUnsetValue(new IntValue().increment(null));
}

@Test
public void increment_IntVariationValue_has_no_effect_if_arg_is_unset() {
verifyUnsetVariationValue(new IntValue().increment(new IntValue()));
public void increment_IntValue_has_no_effect_if_arg_is_unset() {
verifyUnsetValue(new IntValue().increment(new IntValue()));
}

@Test
public void increment_IntVariationValue_increments_by_the_value_of_the_arg() {
public void increment_IntValue_increments_by_the_value_of_the_arg() {
IntValue source = new IntValue().increment(10);
IntValue target = new IntValue().increment(source);

verifySetVariationValue(target, 10);
verifySetValue(target, 10);
}

@Test
public void multiple_calls_to_increment_IntVariationValue_increments_by_the_value_of_the_arg() {
public void multiple_calls_to_increment_IntValue_increments_by_the_value_of_the_arg() {
IntValue target = new IntValue()
.increment(new IntValue().increment(35))
.increment(new IntValue().increment(10));

verifySetVariationValue(target, 45);
verifySetValue(target, 45);
}

@Test
public void multiples_calls_to_increment_int_increment_the_value() {
IntValue variationValue = new IntValue()
IntValue value = new IntValue()
.increment(10)
.increment(95);

verifySetVariationValue(variationValue, 105);
verifySetValue(value, 105);
}

private static void verifyUnsetVariationValue(IntValue variationValue) {
assertThat(variationValue.isSet()).isFalse();
assertThat(variationValue.getValue()).isZero();
private static void verifyUnsetValue(IntValue value) {
assertThat(value.isSet()).isFalse();
assertThat(value.getValue()).isZero();
}

private static void verifySetVariationValue(IntValue variationValue, int expected) {
assertThat(variationValue.isSet()).isTrue();
assertThat(variationValue.getValue()).isEqualTo(expected);
private static void verifySetValue(IntValue value, int expected) {
assertThat(value.isSet()).isTrue();
assertThat(value.getValue()).isEqualTo(expected);
}
}

+ 13
- 13
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/counter/RatingValueTest.java View File

@@ -32,22 +32,22 @@ public class RatingValueTest {

@Test
public void newly_created_value_is_unset_and_has_value_0() {
verifyUnsetVariationValue(new RatingValue());
verifyUnsetValue(new RatingValue());
}

@Test
public void increment_sets_value_and_increments_value() {
verifySetVariationValue(new RatingValue().increment(B), B);
verifySetValue(new RatingValue().increment(B), B);
}

@Test
public void increment_has_no_effect_if_arg_is_null() {
verifyUnsetVariationValue(new RatingValue().increment((RatingValue) null));
verifyUnsetValue(new RatingValue().increment((RatingValue) null));
}

@Test
public void increment_has_no_effect_if_arg_is_unset() {
verifyUnsetVariationValue(new RatingValue().increment(new RatingValue()));
verifyUnsetValue(new RatingValue().increment(new RatingValue()));
}

@Test
@@ -55,7 +55,7 @@ public class RatingValueTest {
RatingValue source = new RatingValue().increment(B);
RatingValue target = new RatingValue().increment(source);

verifySetVariationValue(target, B);
verifySetValue(target, B);
}

@Test
@@ -64,7 +64,7 @@ public class RatingValueTest {
.increment(new RatingValue().increment(B))
.increment(new RatingValue().increment(D));

verifySetVariationValue(target, D);
verifySetValue(target, D);
}

@Test
@@ -73,17 +73,17 @@ public class RatingValueTest {
.increment(B)
.increment(C);

verifySetVariationValue(variationValue, C);
verifySetValue(variationValue, C);
}

private static void verifyUnsetVariationValue(RatingValue variationValue) {
assertThat(variationValue.isSet()).isFalse();
assertThat(variationValue.getValue()).isEqualTo(A);
private static void verifyUnsetValue(RatingValue ratingValue) {
assertThat(ratingValue.isSet()).isFalse();
assertThat(ratingValue.getValue()).isEqualTo(A);
}

private static void verifySetVariationValue(RatingValue variationValue, Rating expected) {
assertThat(variationValue.isSet()).isTrue();
assertThat(variationValue.getValue()).isEqualTo(expected);
private static void verifySetValue(RatingValue ratingValue, Rating expected) {
assertThat(ratingValue.isSet()).isTrue();
assertThat(ratingValue.getValue()).isEqualTo(expected);
}

}

+ 0
- 20
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/formula/coverage/CoverageUtilsTest.java View File

@@ -34,7 +34,6 @@ import static com.google.common.base.Preconditions.checkState;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.sonar.ce.task.projectanalysis.formula.coverage.CoverageUtils.getLongMeasureValue;
import static org.sonar.ce.task.projectanalysis.formula.coverage.CoverageUtils.getMeasureVariations;
import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;

public class CoverageUtilsTest {
@@ -86,25 +85,6 @@ public class CoverageUtilsTest {
.hasMessage("value can not be converted to long because current value type is a DOUBLE");
}

@Test
public void getMeasureVariations_returns_0_in_all_MeasureVariations_if_there_is_no_measure() {
assertThat(getMeasureVariations(fileAggregateContext, SOME_METRIC_KEY)).isEqualTo(DEFAULT_VARIATION);
}

@Test
public void getMeasureVariations_returns_0_in_all_MeasureVariations_if_there_is_measure_has_no_variations() {
fileAggregateContext.put(SOME_METRIC_KEY, newMeasureBuilder().createNoValue());

assertThat(getMeasureVariations(fileAggregateContext, SOME_METRIC_KEY)).isEqualTo(DEFAULT_VARIATION);
}

@Test
public void getMeasureVariations_returns_MeasureVariations_of_measure_when_it_has_one() {
fileAggregateContext.put(SOME_METRIC_KEY, newMeasureBuilder().setVariation(5d).createNoValue());

assertThat(getMeasureVariations(fileAggregateContext, SOME_METRIC_KEY)).isEqualTo(5d);
}

private static class CounterInitializationContextRule extends ExternalResource implements CounterInitializationContext {
private final Map<String, Measure> measures = new HashMap<>();


+ 6
- 13
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/IssueCounterTest.java View File

@@ -34,7 +34,6 @@ import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
import org.sonar.ce.task.projectanalysis.measure.MeasureRepoEntry;
import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
import org.sonar.ce.task.projectanalysis.period.Period;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.db.rule.RuleTesting;

@@ -284,9 +283,9 @@ public class IssueCounterTest {
underTest.beforeComponent(PROJECT);
underTest.afterComponent(PROJECT);

assertVariations(FILE1, entry(NEW_VIOLATIONS_KEY, 2), entry(NEW_CRITICAL_VIOLATIONS_KEY, 2), entry(NEW_BLOCKER_VIOLATIONS_KEY, 0), entry(NEW_MAJOR_VIOLATIONS_KEY, 0),
assertValues(FILE1, entry(NEW_VIOLATIONS_KEY, 2), entry(NEW_CRITICAL_VIOLATIONS_KEY, 2), entry(NEW_BLOCKER_VIOLATIONS_KEY, 0), entry(NEW_MAJOR_VIOLATIONS_KEY, 0),
entry(NEW_CODE_SMELLS_KEY, 1), entry(NEW_BUGS_KEY, 1), entry(NEW_VULNERABILITIES_KEY, 0), entry(NEW_SECURITY_HOTSPOTS_KEY, 1));
assertVariations(PROJECT, entry(NEW_VIOLATIONS_KEY, 2), entry(NEW_CRITICAL_VIOLATIONS_KEY, 2), entry(NEW_BLOCKER_VIOLATIONS_KEY, 0), entry(NEW_MAJOR_VIOLATIONS_KEY, 0),
assertValues(PROJECT, entry(NEW_VIOLATIONS_KEY, 2), entry(NEW_CRITICAL_VIOLATIONS_KEY, 2), entry(NEW_BLOCKER_VIOLATIONS_KEY, 0), entry(NEW_MAJOR_VIOLATIONS_KEY, 0),
entry(NEW_CODE_SMELLS_KEY, 1), entry(NEW_BUGS_KEY, 1), entry(NEW_VULNERABILITIES_KEY, 0), entry(NEW_SECURITY_HOTSPOTS_KEY, 1));
}

@@ -339,18 +338,17 @@ public class IssueCounterTest {
underTest.beforeComponent(PROJECT);
underTest.afterComponent(PROJECT);

assertVariations(FILE1, entry(NEW_VIOLATIONS_KEY, 0), entry(NEW_CRITICAL_VIOLATIONS_KEY, 0), entry(NEW_BLOCKER_VIOLATIONS_KEY, 0), entry(NEW_MAJOR_VIOLATIONS_KEY, 0),
assertValues(FILE1, entry(NEW_VIOLATIONS_KEY, 0), entry(NEW_CRITICAL_VIOLATIONS_KEY, 0), entry(NEW_BLOCKER_VIOLATIONS_KEY, 0), entry(NEW_MAJOR_VIOLATIONS_KEY, 0),
entry(NEW_VULNERABILITIES_KEY, 0));
assertVariations(PROJECT, entry(NEW_VIOLATIONS_KEY, 0), entry(NEW_CRITICAL_VIOLATIONS_KEY, 0), entry(NEW_BLOCKER_VIOLATIONS_KEY, 0), entry(NEW_MAJOR_VIOLATIONS_KEY, 0),
assertValues(PROJECT, entry(NEW_VIOLATIONS_KEY, 0), entry(NEW_CRITICAL_VIOLATIONS_KEY, 0), entry(NEW_BLOCKER_VIOLATIONS_KEY, 0), entry(NEW_MAJOR_VIOLATIONS_KEY, 0),
entry(NEW_VULNERABILITIES_KEY, 0));
}

@SafeVarargs
private final void assertVariations(Component componentRef, MapEntry<String, Integer>... entries) {
private final void assertValues(Component componentRef, MapEntry<String, Integer>... entries) {
assertThat(measureRepository.getRawMeasures(componentRef).entrySet()
.stream()
.filter(e -> e.getValue().hasVariation())
.map(e -> entry(e.getKey(), (int) e.getValue().getVariation())))
.map(e -> entry(e.getKey(), e.getValue().getIntValue())))
.contains(entries);
}

@@ -392,9 +390,4 @@ public class IssueCounterTest {
private DefaultIssue createNewSecurityHotspot() {
return createNewIssue(null, STATUS_OPEN, "MAJOR", RuleType.SECURITY_HOTSPOT);
}

private static Period newPeriod(long date) {
return new Period("mode", null, date);
}

}

+ 14
- 15
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/NewEffortAggregatorTest.java View File

@@ -85,7 +85,7 @@ public class NewEffortAggregatorTest {
underTest.onIssue(FILE, resolved);
underTest.afterComponent(FILE);

assertVariation(FILE, NEW_TECHNICAL_DEBT_KEY, 10 + 30);
assertValue(FILE, NEW_TECHNICAL_DEBT_KEY, 10 + 30);
}

@Test
@@ -110,7 +110,7 @@ public class NewEffortAggregatorTest {
underTest.afterComponent(FILE);

// Only effort of CODE SMELL issue is used
assertVariation(FILE, NEW_TECHNICAL_DEBT_KEY, 10);
assertValue(FILE, NEW_TECHNICAL_DEBT_KEY, 10);
}

@Test
@@ -134,7 +134,7 @@ public class NewEffortAggregatorTest {
underTest.onIssue(FILE, resolved);
underTest.afterComponent(FILE);

assertVariation(FILE, NEW_RELIABILITY_REMEDIATION_EFFORT_KEY, 10 + 30);
assertValue(FILE, NEW_RELIABILITY_REMEDIATION_EFFORT_KEY, 10 + 30);
}

@Test
@@ -159,7 +159,7 @@ public class NewEffortAggregatorTest {
underTest.afterComponent(FILE);

// Only effort of BUG issue is used
assertVariation(FILE, NEW_RELIABILITY_REMEDIATION_EFFORT_KEY, 15);
assertValue(FILE, NEW_RELIABILITY_REMEDIATION_EFFORT_KEY, 15);
}

@Test
@@ -183,7 +183,7 @@ public class NewEffortAggregatorTest {
underTest.onIssue(FILE, oldResolved);
underTest.afterComponent(FILE);

assertVariation(FILE, NEW_SECURITY_REMEDIATION_EFFORT_KEY, 10 + 30);
assertValue(FILE, NEW_SECURITY_REMEDIATION_EFFORT_KEY, 10 + 30);
}

@Test
@@ -208,7 +208,7 @@ public class NewEffortAggregatorTest {
underTest.afterComponent(FILE);

// Only effort of VULNERABILITY issue is used
assertVariation(FILE, NEW_SECURITY_REMEDIATION_EFFORT_KEY, 12);
assertValue(FILE, NEW_SECURITY_REMEDIATION_EFFORT_KEY, 12);
}

@Test
@@ -247,9 +247,9 @@ public class NewEffortAggregatorTest {
underTest.onIssue(PROJECT, oldVulnerabilityProjectIssue);
underTest.afterComponent(PROJECT);

assertVariation(PROJECT, NEW_TECHNICAL_DEBT_KEY, 10 + 30);
assertVariation(PROJECT, NEW_RELIABILITY_REMEDIATION_EFFORT_KEY, 8 + 28);
assertVariation(PROJECT, NEW_SECURITY_REMEDIATION_EFFORT_KEY, 12 + 32);
assertValue(PROJECT, NEW_TECHNICAL_DEBT_KEY, 10 + 30);
assertValue(PROJECT, NEW_RELIABILITY_REMEDIATION_EFFORT_KEY, 8 + 28);
assertValue(PROJECT, NEW_SECURITY_REMEDIATION_EFFORT_KEY, 12 + 32);
}

@Test
@@ -275,15 +275,14 @@ public class NewEffortAggregatorTest {
underTest.beforeComponent(FILE);
underTest.afterComponent(FILE);

assertVariation(FILE, NEW_TECHNICAL_DEBT_KEY, 0);
assertVariation(FILE, NEW_RELIABILITY_REMEDIATION_EFFORT_KEY, 0);
assertVariation(FILE, NEW_SECURITY_REMEDIATION_EFFORT_KEY, 0);
assertValue(FILE, NEW_TECHNICAL_DEBT_KEY, 0);
assertValue(FILE, NEW_RELIABILITY_REMEDIATION_EFFORT_KEY, 0);
assertValue(FILE, NEW_SECURITY_REMEDIATION_EFFORT_KEY, 0);
}

private void assertVariation(Component component, String metricKey, int variation) {
private void assertValue(Component component, String metricKey, int value) {
Measure newMeasure = measureRepository.getRawMeasure(component, metricRepository.getByKey(metricKey)).get();
assertThat(newMeasure.getVariation()).isEqualTo(variation);
assertThat(newMeasure.getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
assertThat(newMeasure.getLongValue()).isEqualTo(value);
}

private DefaultIssue newCodeSmellIssue(long effort) {

+ 6
- 29
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/BestValueOptimizationTest.java View File

@@ -38,28 +38,13 @@ public class BestValueOptimizationTest {
private static final String SOME_DATA = "some_data";
private static final MetricImpl METRIC_BOOLEAN_FALSE = createMetric(Metric.MetricType.BOOL, 6d);
private static final MetricImpl METRIC_BOOLEAN_TRUE = createMetric(Metric.MetricType.BOOL, 1d);
private static final double SOME_EMPTY_VARIATIONS = 0d;

private static Measure.NewMeasureBuilder[] builders_of_non_bestValueOptimized_measures() {
QualityGateStatus someQualityGateStatus = new QualityGateStatus(Measure.Level.ERROR, null);
double someVariations = 2d;
return new Measure.NewMeasureBuilder[] {
newMeasureBuilder().setQualityGateStatus(someQualityGateStatus),
newMeasureBuilder().setQualityGateStatus(someQualityGateStatus).setVariation(someVariations),
newMeasureBuilder().setVariation(someVariations),
newMeasureBuilder().setQualityGateStatus(someQualityGateStatus),
newMeasureBuilder().setQualityGateStatus(someQualityGateStatus).setVariation(someVariations),
};
}

@Test
public void apply_returns_true_for_value_true_for_Boolean_Metric_and_best_value_1() {
Predicate<Measure> underTest = BestValueOptimization.from(METRIC_BOOLEAN_TRUE, FILE_COMPONENT);

assertThat(underTest.test(newMeasureBuilder().create(true))).isTrue();
assertThat(underTest.test(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(true))).isTrue();
assertThat(underTest.test(newMeasureBuilder().create(false))).isFalse();
assertThat(underTest.test(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(false))).isFalse();
}

@Test
@@ -74,10 +59,9 @@ public class BestValueOptimizationTest {
public void apply_returns_false_if_measure_has_anything_else_than_value_for_Boolean_Metric_and_best_value_1() {
Predicate<Measure> underTest = BestValueOptimization.from(METRIC_BOOLEAN_TRUE, FILE_COMPONENT);

for (Measure.NewMeasureBuilder builder : builders_of_non_bestValueOptimized_measures()) {
assertThat(underTest.test(builder.create(true))).isFalse();
assertThat(underTest.test(builder.create(false))).isFalse();
}
Measure.NewMeasureBuilder builder = newMeasureBuilder().setQualityGateStatus(new QualityGateStatus(Measure.Level.ERROR, null));
assertThat(underTest.test(builder.create(true))).isFalse();
assertThat(underTest.test(builder.create(false))).isFalse();
}

@Test
@@ -94,7 +78,6 @@ public class BestValueOptimizationTest {

assertThat(underTest.test(newMeasureBuilder().create(true))).isFalse();
assertThat(underTest.test(newMeasureBuilder().create(false))).isTrue();
assertThat(underTest.test(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(false))).isTrue();
}

@Test
@@ -109,10 +92,9 @@ public class BestValueOptimizationTest {
public void apply_returns_false_if_measure_has_anything_else_than_value_for_Boolean_Metric_and_best_value_not_1() {
Predicate<Measure> underTest = BestValueOptimization.from(METRIC_BOOLEAN_FALSE, FILE_COMPONENT);

for (Measure.NewMeasureBuilder builder : builders_of_non_bestValueOptimized_measures()) {
assertThat(underTest.test(builder.create(true))).isFalse();
assertThat(underTest.test(builder.create(false))).isFalse();
}
Measure.NewMeasureBuilder builder = newMeasureBuilder().setQualityGateStatus(new QualityGateStatus(Measure.Level.ERROR, null));
assertThat(underTest.test(builder.create(true))).isFalse();
assertThat(underTest.test(builder.create(false))).isFalse();
}

@Test
@@ -128,7 +110,6 @@ public class BestValueOptimizationTest {
Predicate<Measure> underTest = BestValueOptimization.from(createMetric(Metric.MetricType.INT, 10), FILE_COMPONENT);

assertThat(underTest.test(newMeasureBuilder().create(10))).isTrue();
assertThat(underTest.test(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(10))).isTrue();
assertThat(underTest.test(newMeasureBuilder().create(11))).isFalse();
}

@@ -137,7 +118,6 @@ public class BestValueOptimizationTest {
Predicate<Measure> underTest = BestValueOptimization.from(createMetric(Metric.MetricType.WORK_DUR, 9511L), FILE_COMPONENT);

assertThat(underTest.test(newMeasureBuilder().create(9511L))).isTrue();
assertThat(underTest.test(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(9511L))).isTrue();
assertThat(underTest.test(newMeasureBuilder().create(963L))).isFalse();
}

@@ -146,9 +126,7 @@ public class BestValueOptimizationTest {
Predicate<Measure> underTest = BestValueOptimization.from(createMetric(Metric.MetricType.RATING, A.getIndex()), FILE_COMPONENT);

assertThat(underTest.test(newMeasureBuilder().create(A.getIndex()))).isTrue();
assertThat(underTest.test(newMeasureBuilder().setVariation(A.getIndex()).createNoValue())).isTrue();
assertThat(underTest.test(newMeasureBuilder().create(B.getIndex()))).isFalse();
assertThat(underTest.test(newMeasureBuilder().setVariation(B.getIndex()).createNoValue())).isFalse();
}

@Test
@@ -156,7 +134,6 @@ public class BestValueOptimizationTest {
Predicate<Measure> underTest = BestValueOptimization.from(createMetric(Metric.MetricType.FLOAT, 36.5d), FILE_COMPONENT);

assertThat(underTest.test(newMeasureBuilder().create(36.5d, 1))).isTrue();
assertThat(underTest.test(newMeasureBuilder().setVariation(SOME_EMPTY_VARIATIONS).create(36.5d, 1))).isTrue();
assertThat(underTest.test(newMeasureBuilder().create(36.6d, 1))).isFalse();
}


+ 0
- 41
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/LiveMeasureDtoToMeasureTest.java View File

@@ -19,9 +19,7 @@
*/
package org.sonar.ce.task.projectanalysis.measure;

import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
import java.util.Optional;
import org.assertj.core.data.Offset;
import org.junit.Test;
@@ -42,12 +40,8 @@ public class LiveMeasureDtoToMeasureTest {
private static final Metric SOME_STRING_METRIC = new MetricImpl("42", "string", "name", Metric.MetricType.STRING);
private static final Metric SOME_BOOLEAN_METRIC = new MetricImpl("42", "boolean", "name", Metric.MetricType.BOOL);
private static final Metric SOME_LEVEL_METRIC = new MetricImpl("42", "level", "name", Metric.MetricType.LEVEL);

private static final String SOME_DATA = "some_data man!";
private static final String SOME_ALERT_TEXT = "some alert text_be_careFul!";
private static final LiveMeasureDto EMPTY_MEASURE_DTO = new LiveMeasureDto();


private LiveMeasureDtoToMeasure underTest = new LiveMeasureDtoToMeasure();

@Test
@@ -190,41 +184,6 @@ public class LiveMeasureDtoToMeasureTest {
assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
}

@DataProvider
public static Object[][] all_types_LiveMeasureDtos() {
return new Object[][] {
{new LiveMeasureDto().setValue(1d), SOME_BOOLEAN_METRIC},
{new LiveMeasureDto().setValue(1d), SOME_INT_METRIC},
{new LiveMeasureDto().setValue(1d), SOME_LONG_METRIC},
{new LiveMeasureDto().setValue(1d), SOME_DOUBLE_METRIC},
{new LiveMeasureDto().setData("1"), SOME_STRING_METRIC},
{new LiveMeasureDto().setData(Level.OK.name()), SOME_LEVEL_METRIC}
};
}

@Test
@UseDataProvider("all_types_LiveMeasureDtos")
public void toMeasure_creates_no_MeasureVariation_if_dto_has_none_whichever_the_ValueType(LiveMeasureDto LiveMeasureDto, Metric metric) {
assertThat(underTest.toMeasure(LiveMeasureDto, metric).get().hasVariation()).isFalse();
}

@Test
@UseDataProvider("all_types_LiveMeasureDtos")
public void toMeasure_creates_MeasureVariation_and_maps_the_right_one(LiveMeasureDto builder, Metric metric) {
assertThat(underTest.toMeasure(builder.setVariation(1d), metric).get().getVariation()).isOne();
}

@Test
public void toMeasure_creates_MeasureVariation_and_maps_the_right_one() {
LiveMeasureDto LiveMeasureDto = new LiveMeasureDto()
.setData("1")
.setVariation(2d);

Optional<Measure> measure = underTest.toMeasure(LiveMeasureDto, SOME_STRING_METRIC);

assertThat(measure.get().getVariation()).isEqualTo(2);
}

@Test
public void toMeasure_should_not_loose_decimals_of_float_values() {
MetricImpl metric = new MetricImpl("42", "double", "name", Metric.MetricType.FLOAT, 5, null, false, false);

+ 0
- 23
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureDtoToMeasureTest.java View File

@@ -297,29 +297,6 @@ public class MeasureDtoToMeasureTest {
};
}

@Test
@UseDataProvider("all_types_MeasureDtos")
public void toMeasure_creates_no_MeasureVariation_if_dto_has_none_whichever_the_ValueType(MeasureDto measureDto, Metric metric) {
assertThat(underTest.toMeasure(measureDto, metric).get().hasVariation()).isFalse();
}

@Test
@UseDataProvider("all_types_MeasureDtos")
public void toMeasure_creates_MeasureVariation_and_maps_the_right_one(MeasureDto builder, Metric metric) {
assertThat(underTest.toMeasure(builder.setVariation(1d), metric).get().getVariation()).isOne();
}

@Test
public void toMeasure_creates_MeasureVariation_and_maps_the_right_one() {
MeasureDto measureDto = new MeasureDto()
.setData("1")
.setVariation(2d);

Optional<Measure> measure = underTest.toMeasure(measureDto, SOME_STRING_METRIC);

assertThat(measure.get().getVariation()).isEqualTo(2);
}

@Test
public void toMeasure_should_not_loose_decimals_of_float_values() {
MetricImpl metric = new MetricImpl("42", "double", "name", Metric.MetricType.FLOAT, 5, null, false, false);

+ 0
- 7
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureTest.java View File

@@ -251,12 +251,6 @@ public class MeasureTest {
.isInstanceOf(UnsupportedOperationException.class);
}

@Test
public void updateMeasureBuilder_setVariations_throws_USO_if_measure_already_has_Variations() {
assertThatThrownBy(() -> Measure.updatedMeasureBuilder(newMeasureBuilder().setVariation(1d).createNoValue()).setVariation(2d))
.isInstanceOf(UnsupportedOperationException.class);
}

@Test
@UseDataProvider("all")
public void updateMeasureBuilder_creates_Measure_with_same_immutable_properties(Measure measure) {
@@ -264,7 +258,6 @@ public class MeasureTest {

assertThat(newMeasure.getValueType()).isEqualTo(measure.getValueType());
assertThat(newMeasure.hasQualityGateStatus()).isEqualTo(measure.hasQualityGateStatus());
assertThat(newMeasure.hasVariation()).isEqualTo(measure.hasVariation());
}

@Test

+ 0
- 16
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureToMeasureDtoTest.java View File

@@ -43,7 +43,6 @@ public class MeasureToMeasureDtoTest {
private static final MetricImpl SOME_METRIC = new MetricImpl("42", "metric_key", "metric_name", Metric.MetricType.STRING);
private static final String SOME_DATA = "some_data";
private static final String SOME_STRING = "some_string";
private static final double SOME_VARIATIONS = 1d;
private static final MetricImpl SOME_BOOLEAN_METRIC = new MetricImpl("1", "1", "1", Metric.MetricType.BOOL);
private static final MetricImpl SOME_INT_METRIC = new MetricImpl("2", "2", "2", Metric.MetricType.INT);
private static final MetricImpl SOME_LONG_METRIC = new MetricImpl("3", "3", "3", Metric.MetricType.DISTRIB);
@@ -90,21 +89,6 @@ public class MeasureToMeasureDtoTest {
};
}

@Test
@UseDataProvider("all_types_Measures")
public void toMeasureDto_returns_Dto_without_any_variation_if_Measure_has_no_MeasureVariations(Measure measure, Metric metric) {
MeasureDto measureDto = underTest.toMeasureDto(measure, metric, SOME_COMPONENT);

assertThat(measureDto.getVariation()).isNull();
}

@Test
public void toMeasureDto_returns_Dto_with_variation_if_Measure_has_MeasureVariations() {
MeasureDto measureDto = underTest.toMeasureDto(Measure.newMeasureBuilder().setVariation(SOME_VARIATIONS).create(SOME_STRING), SOME_STRING_METRIC, SOME_COMPONENT);

assertThat(measureDto.getVariation()).isEqualTo(1d);
}

@Test
@UseDataProvider("all_types_Measures")
public void toMeasureDto_returns_Dto_without_alertStatus_nor_alertText_if_Measure_has_no_QualityGateStatus(Measure measure, Metric metric) {

+ 1
- 44
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitygate/ConditionEvaluatorTest.java View File

@@ -35,16 +35,15 @@ import static com.google.common.collect.FluentIterable.from;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.Assert.fail;
import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;
import static org.sonar.ce.task.projectanalysis.measure.Measure.Level.ERROR;
import static org.sonar.ce.task.projectanalysis.measure.Measure.Level.OK;
import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;
import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType;
import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.BOOL;
import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.DATA;
import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.DISTRIB;
import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.FLOAT;
import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.INT;
import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.LEVEL;
import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.PERCENT;
import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.RATING;
import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.STRING;
@@ -158,44 +157,6 @@ public class ConditionEvaluatorTest {
};
}

@Test
@UseDataProvider("numericNewMetricTypes")
public void test_condition_on_numeric_new_metric(MetricType metricType) {
Metric metric = createNewMetric(metricType);
Measure measure = newMeasureBuilder().setVariation(3d).createNoValue();

assertThat(underTest.evaluate(new Condition(metric, GREATER_THAN.getDbValue(), "3"), measure)).hasLevel(OK);
assertThat(underTest.evaluate(new Condition(metric, GREATER_THAN.getDbValue(), "2"), measure)).hasLevel(ERROR);
}

@Test
@UseDataProvider("numericNewMetricTypes")
public void condition_on_new_metric_without_value_is_OK(MetricType metricType) {
Metric metric = createNewMetric(metricType);
Measure measure = newMeasureBuilder().createNoValue();

assertThat(underTest.evaluate(new Condition(metric, GREATER_THAN.getDbValue(), "3"), measure)).hasLevel(OK).hasValue(null);
}

@DataProvider
public static Object[][] numericNewMetricTypes() {
return new Object[][] {
{FLOAT},
{INT},
{WORK_DUR},
};
}

@Test
public void fail_when_condition_on_leak_period_is_using_unsupported_metric() {
Metric metric = createNewMetric(LEVEL);
Measure measure = newMeasureBuilder().setVariation(0d).createNoValue();

assertThatThrownBy(() -> underTest.evaluate(new Condition(metric, LESS_THAN.getDbValue(), "3"), measure))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Unsupported metric type LEVEL");
}

@Test
public void test_condition_on_rating() {
Metric metric = createMetric(RATING);
@@ -212,8 +173,4 @@ public class ConditionEvaluatorTest {
private static MetricImpl createMetric(MetricType metricType) {
return new MetricImpl("1", "key", "name", metricType);
}

private static MetricImpl createNewMetric(MetricType metricType) {
return new MetricImpl("1", "new_key", "name", metricType);
}
}

+ 10
- 10
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewMaintainabilityMeasuresVisitorTest.java View File

@@ -64,7 +64,7 @@ import static org.sonar.ce.task.projectanalysis.measure.MeasureAssert.assertThat
import static org.sonar.server.measure.Rating.A;
import static org.sonar.server.measure.Rating.D;

public class NewMaintainabilityMeasuresVisitorTest {
public class NewMaintainabilityMeasuresVisitorTest {

private static final double[] RATING_GRID = new double[] {0.1, 0.2, 0.5, 1};

@@ -72,7 +72,7 @@ public class NewMaintainabilityMeasuresVisitorTest {
private static final long LANGUAGE_1_DEV_COST = 30L;
private static final int ROOT_REF = 1;
private static final int LANGUAGE_1_FILE_REF = 11111;
private static final Offset<Double> VARIATION_COMPARISON_OFFSET = Offset.offset(0.01);
private static final Offset<Double> VALUE_COMPARISON_OFFSET = Offset.offset(0.01);

@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
@@ -422,8 +422,8 @@ public class NewMaintainabilityMeasuresVisitorTest {
return ReportComponent.builder(type, ref).setKey(String.valueOf(ref));
}

private Measure createNewDebtMeasure(double variation) {
return newMeasureBuilder().setVariation(variation).createNoValue();
private Measure createNewDebtMeasure(long value) {
return newMeasureBuilder().create(value);
}

private static Measure createNclocDataMeasure(Integer... nclocLines) {
@@ -449,16 +449,16 @@ public class NewMaintainabilityMeasuresVisitorTest {
.isAbsent();
}

private void assertNewDebtRatioValues(int componentRef, double expectedVariation) {
assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SQALE_DEBT_RATIO_KEY)).hasVariation(expectedVariation, VARIATION_COMPARISON_OFFSET);
private void assertNewDebtRatioValues(int componentRef, double expectedValue) {
assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SQALE_DEBT_RATIO_KEY)).hasValue(expectedValue, VALUE_COMPARISON_OFFSET);
}

private void assertNewDevelopmentCostValues(int componentRef, long expectedVariation) {
assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_DEVELOPMENT_COST_KEY)).hasVariation(expectedVariation, VARIATION_COMPARISON_OFFSET);
private void assertNewDevelopmentCostValues(int componentRef, float expectedValue) {
assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_DEVELOPMENT_COST_KEY)).hasValue(expectedValue, VALUE_COMPARISON_OFFSET);
}

private void assertNewMaintainability(int componentRef, Rating expectedVariation) {
assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_MAINTAINABILITY_RATING_KEY)).hasVariation(expectedVariation.getIndex());
private void assertNewMaintainability(int componentRef, Rating expectedValue) {
assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_MAINTAINABILITY_RATING_KEY)).hasValue(expectedValue.getIndex());
}

private void assertNoNewMaintainability(int componentRef) {

+ 1
- 2
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewReliabilityAndSecurityRatingMeasuresVisitorTest.java View File

@@ -322,8 +322,7 @@ public class NewReliabilityAndSecurityRatingMeasuresVisitorTest {
}

private void verifyAddedRawMeasureOnLeakPeriod(int componentRef, String metricKey, Rating rating) {
MeasureAssert.assertThat(measureRepository.getAddedRawMeasure(componentRef, metricKey))
.hasVariation(rating.getIndex());
MeasureAssert.assertThat(measureRepository.getAddedRawMeasure(componentRef, metricKey)).hasValue(rating.getIndex());
}

private DefaultIssue newBugIssue(long effort, String severity) {

+ 6
- 6
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewSecurityReviewMeasuresVisitorTest.java View File

@@ -70,7 +70,7 @@ import static org.sonar.server.measure.Rating.D;
import static org.sonar.server.measure.Rating.E;

public class NewSecurityReviewMeasuresVisitorTest {
private static final Offset<Double> VARIATION_COMPARISON_OFFSET = Offset.offset(0.01);
private static final Offset<Double> VALUE_COMPARISON_OFFSET = Offset.offset(0.01);
private static final String LANGUAGE_KEY_1 = "lKey1";

private static final int PROJECT_REF = 1;
@@ -341,10 +341,10 @@ public class NewSecurityReviewMeasuresVisitorTest {
}

private void verifyRatingAndReviewedMeasures(int componentRef, Rating expectedReviewRating, @Nullable Double expectedHotspotsReviewed) {
assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_REVIEW_RATING_KEY)).hasVariation(expectedReviewRating.getIndex());
assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_REVIEW_RATING_KEY)).hasValue(expectedReviewRating.getIndex());
if (expectedHotspotsReviewed != null) {
assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_REVIEWED_KEY)).hasVariation(expectedHotspotsReviewed,
VARIATION_COMPARISON_OFFSET);
assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_REVIEWED_KEY)).hasValue(expectedHotspotsReviewed,
VALUE_COMPARISON_OFFSET);
} else {
assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_REVIEWED_KEY)).isAbsent();
}
@@ -354,12 +354,12 @@ public class NewSecurityReviewMeasuresVisitorTest {
if (hotspotsReviewed == null) {
Assertions.assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY)).isEmpty();
} else {
assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY)).hasVariation(hotspotsReviewed);
assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY)).hasValue(hotspotsReviewed);
}
if (hotspotsReviewed == null) {
Assertions.assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY)).isEmpty();
} else {
assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY)).hasVariation(hotspotsToReview);
assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY)).hasValue(hotspotsToReview);
}
}


+ 50
- 48
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/NewCoverageMeasuresStepTest.java View File

@@ -179,10 +179,10 @@ public class NewCoverageMeasuresStepTest {
underTest.execute(new TestComputationStepContext());

assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_COMPONENT.getReportAttributes().getRef()))).contains(
entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(2d)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(1d)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(0d)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(0d)));
entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(2)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(1)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(0)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(0)));
}

@Test
@@ -204,36 +204,36 @@ public class NewCoverageMeasuresStepTest {

// files
assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_1_REF))).contains(
entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(5d)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(3d)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(7d)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(4d)));
entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(5)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(3)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(7)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(4)));
assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_2_REF))).contains(
entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(5d)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(4d)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(27d)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(14d)));
entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(5)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(4)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(27)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(14)));
assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_3_REF))).contains(
entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(5d)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(2d)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(17d)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(9d)));
entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(5)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(2)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(17)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(9)));
// directories
assertThat(toEntries(measureRepository.getAddedRawMeasures(DIRECTORY_1_REF))).contains(
entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(5d)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(3d)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(7d)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(4d)));
entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(5)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(3)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(7)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(4)));
assertThat(toEntries(measureRepository.getAddedRawMeasures(DIRECTORY_2_REF))).contains(
entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(10d)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(6d)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(44d)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(23d)));
entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(10)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(6)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(44)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(23)));
// submodule
MeasureRepoEntry[] repoEntriesFromProject = {entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(15d)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(9d)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(51d)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(27d))};
MeasureRepoEntry[] repoEntriesFromProject = {entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(15)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(9)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(51)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(27))};
// project
assertThat(toEntries(measureRepository.getAddedRawMeasures(ROOT_REF))).contains(repoEntriesFromProject);
}
@@ -266,15 +266,15 @@ public class NewCoverageMeasuresStepTest {
private void verify_aggregates_variations(LinesAndConditionsWithUncoveredMetricKeys metricKeys, String codeCoverageKey, String lineCoverageKey, String branchCoverageKey) {
treeRootHolder.setRoot(MULTIPLE_FILES_TREE);
measureRepository
.addRawMeasure(FILE_1_REF, metricKeys.getLines(), createMeasure(3000d))
.addRawMeasure(FILE_1_REF, metricKeys.getConditions(), createMeasure(300d))
.addRawMeasure(FILE_1_REF, metricKeys.getUncoveredLines(), createMeasure(30d))
.addRawMeasure(FILE_1_REF, metricKeys.getUncoveredConditions(), createMeasure(9d))
.addRawMeasure(FILE_1_REF, metricKeys.getLines(), createMeasure(3000))
.addRawMeasure(FILE_1_REF, metricKeys.getConditions(), createMeasure(300))
.addRawMeasure(FILE_1_REF, metricKeys.getUncoveredLines(), createMeasure(30))
.addRawMeasure(FILE_1_REF, metricKeys.getUncoveredConditions(), createMeasure(9))

.addRawMeasure(FILE_2_REF, metricKeys.getLines(), createMeasure(2000d))
.addRawMeasure(FILE_2_REF, metricKeys.getConditions(), createMeasure(400d))
.addRawMeasure(FILE_2_REF, metricKeys.getUncoveredLines(), createMeasure(200d))
.addRawMeasure(FILE_2_REF, metricKeys.getUncoveredConditions(), createMeasure(16d));
.addRawMeasure(FILE_2_REF, metricKeys.getLines(), createMeasure(2000))
.addRawMeasure(FILE_2_REF, metricKeys.getConditions(), createMeasure(400))
.addRawMeasure(FILE_2_REF, metricKeys.getUncoveredLines(), createMeasure(200))
.addRawMeasure(FILE_2_REF, metricKeys.getUncoveredConditions(), createMeasure(16));

underTest.execute(new TestComputationStepContext());

@@ -309,10 +309,10 @@ public class NewCoverageMeasuresStepTest {

private void verify_only_zero_measures_on_new_lines_and_conditions_measures(Component component) {
assertThat(toEntries(measureRepository.getAddedRawMeasures(component.getReportAttributes().getRef()))).containsOnly(
entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(0d)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(0d)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(0d)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(0d)));
entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(0)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(0)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(0)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(0)));
}

private static final class LineCoverageValues {
@@ -334,16 +334,18 @@ public class NewCoverageMeasuresStepTest {
underTest.execute(new TestComputationStepContext());

assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_COMPONENT.getReportAttributes().getRef()))).contains(
entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(5d)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(3d)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(7d)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(4d)));
entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(5)),
entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(3)),
entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(7)),
entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(4)));
}

private static Measure createMeasure(Double expectedVariation) {
return newMeasureBuilder()
.setVariation(expectedVariation)
.createNoValue();
private static Measure createMeasure(int expectedValue) {
return newMeasureBuilder().create(expectedValue);
}

private static Measure createMeasure(double expectedValue) {
return newMeasureBuilder().create(expectedValue);
}

private void setNewLines(Component c, Integer... lines) {

+ 49
- 48
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/NewSizeMeasuresStepTest.java View File

@@ -103,13 +103,13 @@ public class NewSizeMeasuresStepTest {
setNewLines(FILE_1, FILE_2, FILE_4);
underTest.execute(new TestComputationStepContext());

assertRawMeasureValueOnPeriod(FILE_1_REF, NEW_LINES_KEY, 11);
assertRawMeasureValueOnPeriod(FILE_2_REF, NEW_LINES_KEY, 11);
assertRawMeasureValue(FILE_1_REF, NEW_LINES_KEY, 11);
assertRawMeasureValue(FILE_2_REF, NEW_LINES_KEY, 11);
assertNoRawMeasure(FILE_3_REF, NEW_LINES_KEY);
assertRawMeasureValueOnPeriod(FILE_4_REF, NEW_LINES_KEY, 11);
assertRawMeasureValueOnPeriod(DIRECTORY_REF, NEW_LINES_KEY, 22);
assertRawMeasureValue(FILE_4_REF, NEW_LINES_KEY, 11);
assertRawMeasureValue(DIRECTORY_REF, NEW_LINES_KEY, 22);
assertNoRawMeasure(DIRECTORY_2_REF, NEW_LINES_KEY);
assertRawMeasureValueOnPeriod(ROOT_REF, NEW_LINES_KEY, 33);
assertRawMeasureValue(ROOT_REF, NEW_LINES_KEY, 33);
}

@Test
@@ -118,13 +118,13 @@ public class NewSizeMeasuresStepTest {

underTest.execute(new TestComputationStepContext());

assertRawMeasureValueOnPeriod(FILE_1_REF, NEW_LINES_KEY, 2);
assertRawMeasureValueOnPeriod(FILE_2_REF, NEW_LINES_KEY, 2);
assertRawMeasureValue(FILE_1_REF, NEW_LINES_KEY, 2);
assertRawMeasureValue(FILE_2_REF, NEW_LINES_KEY, 2);
assertNoRawMeasure(FILE_3_REF, NEW_LINES_KEY);
assertRawMeasureValueOnPeriod(FILE_4_REF, NEW_LINES_KEY, 2);
assertRawMeasureValueOnPeriod(DIRECTORY_REF, NEW_LINES_KEY, 4);
assertRawMeasureValue(FILE_4_REF, NEW_LINES_KEY, 2);
assertRawMeasureValue(DIRECTORY_REF, NEW_LINES_KEY, 4);
assertNoRawMeasure(DIRECTORY_2_REF, NEW_LINES_KEY);
assertRawMeasureValueOnPeriod(ROOT_REF, NEW_LINES_KEY, 6);
assertRawMeasureValue(ROOT_REF, NEW_LINES_KEY, 6);
}

@Test
@@ -141,7 +141,7 @@ public class NewSizeMeasuresStepTest {

underTest.execute(new TestComputationStepContext());

assertRawMeasureValueOnPeriod(FILE_1_REF, NEW_DUPLICATED_LINES_KEY, 2d);
assertRawMeasureValue(FILE_1_REF, NEW_DUPLICATED_LINES_KEY, 2);
}

@Test
@@ -152,7 +152,7 @@ public class NewSizeMeasuresStepTest {

underTest.execute(new TestComputationStepContext());

assertRawMeasureValueOnPeriod(FILE_1_REF, NEW_DUPLICATED_LINES_KEY, 1d);
assertRawMeasureValue(FILE_1_REF, NEW_DUPLICATED_LINES_KEY, 1);
}

@Test
@@ -163,7 +163,7 @@ public class NewSizeMeasuresStepTest {

underTest.execute(new TestComputationStepContext());

assertRawMeasureValueOnPeriod(FILE_1_REF, NEW_DUPLICATED_LINES_KEY, 1d);
assertRawMeasureValue(FILE_1_REF, NEW_DUPLICATED_LINES_KEY, 1);
}

@Test
@@ -174,7 +174,7 @@ public class NewSizeMeasuresStepTest {

underTest.execute(new TestComputationStepContext());

assertRawMeasureValueOnPeriod(FILE_1_REF, NEW_DUPLICATED_LINES_KEY, 6d);
assertRawMeasureValue(FILE_1_REF, NEW_DUPLICATED_LINES_KEY, 6);
}

@Test
@@ -186,7 +186,7 @@ public class NewSizeMeasuresStepTest {

underTest.execute(new TestComputationStepContext());

assertRawMeasureValueOnPeriod(FILE_1_REF, NEW_DUPLICATED_LINES_KEY, 11d);
assertRawMeasureValue(FILE_1_REF, NEW_DUPLICATED_LINES_KEY, 11);
}

@Test
@@ -198,13 +198,13 @@ public class NewSizeMeasuresStepTest {

underTest.execute(new TestComputationStepContext());

assertRawMeasureValueOnPeriod(FILE_1_REF, NEW_DUPLICATED_LINES_KEY, 2d);
assertRawMeasureValueOnPeriod(FILE_2_REF, NEW_DUPLICATED_LINES_KEY, 0d);
assertRawMeasureValueOnPeriod(FILE_3_REF, NEW_DUPLICATED_LINES_KEY, 9d);
assertRawMeasureValueOnPeriod(FILE_4_REF, NEW_DUPLICATED_LINES_KEY, 11d);
assertRawMeasureValueOnPeriod(DIRECTORY_REF, NEW_DUPLICATED_LINES_KEY, 2d);
assertRawMeasureValue(FILE_1_REF, NEW_DUPLICATED_LINES_KEY, 2);
assertRawMeasureValue(FILE_2_REF, NEW_DUPLICATED_LINES_KEY, 0);
assertRawMeasureValue(FILE_3_REF, NEW_DUPLICATED_LINES_KEY, 9);
assertRawMeasureValue(FILE_4_REF, NEW_DUPLICATED_LINES_KEY, 11);
assertRawMeasureValue(DIRECTORY_REF, NEW_DUPLICATED_LINES_KEY, 2);
assertNoRawMeasure(DIRECTORY_2_REF, NEW_DUPLICATED_LINES_KEY);
assertRawMeasureValueOnPeriod(ROOT_REF, NEW_DUPLICATED_LINES_KEY, 22d);
assertRawMeasureValue(ROOT_REF, NEW_DUPLICATED_LINES_KEY, 22);
}

@Test
@@ -217,13 +217,13 @@ public class NewSizeMeasuresStepTest {

underTest.execute(new TestComputationStepContext());

assertRawMeasureValueOnPeriod(FILE_1_REF, NEW_DUPLICATED_LINES_KEY, 2d);
assertRawMeasureValueOnPeriod(FILE_2_REF, NEW_DUPLICATED_LINES_KEY, 0d);
assertRawMeasureValueOnPeriod(FILE_3_REF, NEW_DUPLICATED_LINES_KEY, 2d);
assertRawMeasureValueOnPeriod(FILE_4_REF, NEW_DUPLICATED_LINES_KEY, 2d);
assertRawMeasureValueOnPeriod(DIRECTORY_REF, NEW_DUPLICATED_LINES_KEY, 2d);
assertRawMeasureValue(FILE_1_REF, NEW_DUPLICATED_LINES_KEY, 2);
assertRawMeasureValue(FILE_2_REF, NEW_DUPLICATED_LINES_KEY, 0);
assertRawMeasureValue(FILE_3_REF, NEW_DUPLICATED_LINES_KEY, 2);
assertRawMeasureValue(FILE_4_REF, NEW_DUPLICATED_LINES_KEY, 2);
assertRawMeasureValue(DIRECTORY_REF, NEW_DUPLICATED_LINES_KEY, 2);
assertNoRawMeasure(DIRECTORY_2_REF, NEW_DUPLICATED_LINES_KEY);
assertRawMeasureValueOnPeriod(ROOT_REF, NEW_DUPLICATED_LINES_KEY, 6d);
assertRawMeasureValue(ROOT_REF, NEW_DUPLICATED_LINES_KEY, 6);
}

@Test
@@ -243,7 +243,7 @@ public class NewSizeMeasuresStepTest {

underTest.execute(new TestComputationStepContext());

assertRawMeasureValueOnPeriod(FILE_1_REF, NEW_BLOCKS_DUPLICATED_KEY, 4);
assertRawMeasureValue(FILE_1_REF, NEW_BLOCKS_DUPLICATED_KEY, 4);
}

@Test
@@ -254,7 +254,7 @@ public class NewSizeMeasuresStepTest {

underTest.execute(new TestComputationStepContext());

assertRawMeasureValueOnPeriod(FILE_1_REF, NEW_BLOCKS_DUPLICATED_KEY, 4);
assertRawMeasureValue(FILE_1_REF, NEW_BLOCKS_DUPLICATED_KEY, 4);
}

@Test
@@ -264,7 +264,7 @@ public class NewSizeMeasuresStepTest {

underTest.execute(new TestComputationStepContext());

assertRawMeasureValueOnPeriod(FILE_1_REF, NEW_BLOCKS_DUPLICATED_KEY, 1);
assertRawMeasureValue(FILE_1_REF, NEW_BLOCKS_DUPLICATED_KEY, 1);
}

@Test
@@ -274,7 +274,7 @@ public class NewSizeMeasuresStepTest {

underTest.execute(new TestComputationStepContext());

assertRawMeasureValueOnPeriod(FILE_1_REF, NEW_BLOCKS_DUPLICATED_KEY, 1);
assertRawMeasureValue(FILE_1_REF, NEW_BLOCKS_DUPLICATED_KEY, 1);
}

@Test
@@ -286,12 +286,12 @@ public class NewSizeMeasuresStepTest {

underTest.execute(new TestComputationStepContext());

assertRawMeasureValueOnPeriod(FILE_1_REF, NEW_BLOCKS_DUPLICATED_KEY, 10);
assertRawMeasureValueOnPeriod(FILE_2_REF, NEW_BLOCKS_DUPLICATED_KEY, 2);
assertRawMeasureValueOnPeriod(FILE_3_REF, NEW_BLOCKS_DUPLICATED_KEY, 0);
assertRawMeasureValueOnPeriod(FILE_4_REF, NEW_BLOCKS_DUPLICATED_KEY, 6);
assertRawMeasureValueOnPeriod(DIRECTORY_REF, NEW_BLOCKS_DUPLICATED_KEY, 12);
assertRawMeasureValueOnPeriod(ROOT_REF, NEW_BLOCKS_DUPLICATED_KEY, 18);
assertRawMeasureValue(FILE_1_REF, NEW_BLOCKS_DUPLICATED_KEY, 10);
assertRawMeasureValue(FILE_2_REF, NEW_BLOCKS_DUPLICATED_KEY, 2);
assertRawMeasureValue(FILE_3_REF, NEW_BLOCKS_DUPLICATED_KEY, 0);
assertRawMeasureValue(FILE_4_REF, NEW_BLOCKS_DUPLICATED_KEY, 6);
assertRawMeasureValue(DIRECTORY_REF, NEW_BLOCKS_DUPLICATED_KEY, 12);
assertRawMeasureValue(ROOT_REF, NEW_BLOCKS_DUPLICATED_KEY, 18);
}

@Test
@@ -358,22 +358,23 @@ public class NewSizeMeasuresStepTest {
}
}

private void assertRawMeasureValueOnPeriod(int componentRef, String metricKey, double expectedVariation) {
assertRawMeasureValue(componentRef, metricKey, expectedVariation);
private void assertRawMeasureValue(int componentRef, String metricKey, int expectedValue) {
int value = measureRepository.getAddedRawMeasure(componentRef, metricKey).get().getIntValue();
assertThat(value).isEqualTo(expectedValue);
}

private void assertRawMeasureValue(int componentRef, String metricKey, double expectedVariation) {
double variation = measureRepository.getAddedRawMeasure(componentRef, metricKey).get().getVariation();
assertThat(variation).isEqualTo(expectedVariation, DEFAULT_OFFSET);
private void assertRawMeasureValue(int componentRef, String metricKey, double expectedValue) {
double value = measureRepository.getAddedRawMeasure(componentRef, metricKey).get().getDoubleValue();
assertThat(value).isEqualTo(expectedValue, DEFAULT_OFFSET);
}

private void assertComputedAndAggregatedToZeroInt(String metricKey) {
assertRawMeasureValueOnPeriod(FILE_1_REF, metricKey, 0);
assertRawMeasureValueOnPeriod(FILE_2_REF, metricKey, 0);
assertRawMeasureValueOnPeriod(FILE_3_REF, metricKey, 0);
assertRawMeasureValueOnPeriod(FILE_4_REF, metricKey, 0);
assertRawMeasureValueOnPeriod(DIRECTORY_REF, metricKey, 0);
assertRawMeasureValueOnPeriod(ROOT_REF, metricKey, 0);
assertRawMeasureValue(FILE_1_REF, metricKey, 0);
assertRawMeasureValue(FILE_2_REF, metricKey, 0);
assertRawMeasureValue(FILE_3_REF, metricKey, 0);
assertRawMeasureValue(FILE_4_REF, metricKey, 0);
assertRawMeasureValue(DIRECTORY_REF, metricKey, 0);
assertRawMeasureValue(ROOT_REF, metricKey, 0);
}

private void assertNoRawMeasure(int componentRef, String metricKey) {

+ 2
- 3
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistLiveMeasuresStepTest.java View File

@@ -135,13 +135,12 @@ public class PersistLiveMeasuresStepTest extends BaseStepTest {
@Test
public void measures_on_new_code_period_are_persisted() {
prepareProject();
measureRepository.addRawMeasure(REF_1, INT_METRIC.getKey(), newMeasureBuilder().setVariation(42.0).createNoValue());
measureRepository.addRawMeasure(REF_1, INT_METRIC.getKey(), newMeasureBuilder().create(42.0));

step().execute(context);

LiveMeasureDto persistedMeasure = selectMeasure("project-uuid", INT_METRIC).get();
assertThat(persistedMeasure.getValue()).isNull();
assertThat(persistedMeasure.getVariation()).isEqualTo(42.0);
assertThat(persistedMeasure.getValue()).isEqualTo(42.0);
verifyStatistics(context, 1);
}


+ 2
- 3
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistMeasuresStepTest.java View File

@@ -136,13 +136,12 @@ public class PersistMeasuresStepTest extends BaseStepTest {
@Test
public void measures_on_new_code_period_are_persisted() {
prepareProject();
measureRepository.addRawMeasure(REF_1, INT_METRIC.getKey(), newMeasureBuilder().setVariation(42.0).createNoValue());
measureRepository.addRawMeasure(REF_1, INT_METRIC.getKey(), newMeasureBuilder().create(42.0));

TestComputationStepContext context = execute();

MeasureDto persistedMeasure = selectMeasure("project-uuid", INT_METRIC).get();
assertThat(persistedMeasure.getValue()).isNull();
assertThat(persistedMeasure.getVariation()).isEqualTo(42.0);
assertThat(persistedMeasure.getValue()).isEqualTo(42.0);
assertNbOfInserts(context, 1);
}


+ 1
- 3
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/QualityGateMeasuresStepTest.java View File

@@ -261,9 +261,7 @@ public class QualityGateMeasuresStepTest {
Condition periodCondition = createLessThanCondition(INT_METRIC_1, "1");

qualityGateHolder.setQualityGate(new QualityGate(SOME_QG_UUID, SOME_QG_NAME, of(fixedCondition, periodCondition)));
Measure measure = newMeasureBuilder()
.setVariation(rawValue)
.create(rawValue, null);
Measure measure = newMeasureBuilder().create(rawValue);
measureRepository.addRawMeasure(PROJECT_REF, INT_METRIC_1_KEY, measure);

underTest.execute(new TestComputationStepContext());

+ 5
- 5
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/SmallChangesetQualityGateSpecialCaseTest.java View File

@@ -66,7 +66,7 @@ public class SmallChangesetQualityGateSpecialCaseTest {
mapSettings.setProperty(CoreProperties.QUALITY_GATE_IGNORE_SMALL_CHANGES, true);
QualityGateMeasuresStep.MetricEvaluationResult metricEvaluationResult = generateEvaluationResult(NEW_COVERAGE_KEY, ERROR);
Component project = generateNewRootProject();
measureRepository.addRawMeasure(PROJECT_REF, CoreMetrics.NEW_LINES_KEY, newMeasureBuilder().setVariation(19).create(1000));
measureRepository.addRawMeasure(PROJECT_REF, CoreMetrics.NEW_LINES_KEY, newMeasureBuilder().create(19));

boolean result = underTest.appliesTo(project, metricEvaluationResult);

@@ -78,7 +78,7 @@ public class SmallChangesetQualityGateSpecialCaseTest {
mapSettings.setProperty(CoreProperties.QUALITY_GATE_IGNORE_SMALL_CHANGES, false);
QualityGateMeasuresStep.MetricEvaluationResult metricEvaluationResult = generateEvaluationResult(NEW_COVERAGE_KEY, ERROR);
Component project = generateNewRootProject();
measureRepository.addRawMeasure(PROJECT_REF, CoreMetrics.NEW_LINES_KEY, newMeasureBuilder().setVariation(19).create(1000));
measureRepository.addRawMeasure(PROJECT_REF, CoreMetrics.NEW_LINES_KEY, newMeasureBuilder().create(19));

boolean result = underTest.appliesTo(project, metricEvaluationResult);

@@ -89,7 +89,7 @@ public class SmallChangesetQualityGateSpecialCaseTest {
public void should_not_change_for_bigger_changesets() {
QualityGateMeasuresStep.MetricEvaluationResult metricEvaluationResult = generateEvaluationResult(NEW_COVERAGE_KEY, ERROR);
Component project = generateNewRootProject();
measureRepository.addRawMeasure(PROJECT_REF, CoreMetrics.NEW_LINES_KEY, newMeasureBuilder().setVariation(20).create(1000));
measureRepository.addRawMeasure(PROJECT_REF, CoreMetrics.NEW_LINES_KEY, newMeasureBuilder().create(20));

boolean result = underTest.appliesTo(project, metricEvaluationResult);

@@ -100,7 +100,7 @@ public class SmallChangesetQualityGateSpecialCaseTest {
public void should_not_change_issue_related_metrics() {
QualityGateMeasuresStep.MetricEvaluationResult metricEvaluationResult = generateEvaluationResult(NEW_BUGS_KEY, ERROR);
Component project = generateNewRootProject();
measureRepository.addRawMeasure(PROJECT_REF, CoreMetrics.NEW_LINES_KEY, newMeasureBuilder().setVariation(19).create(1000));
measureRepository.addRawMeasure(PROJECT_REF, CoreMetrics.NEW_LINES_KEY, newMeasureBuilder().create(19));

boolean result = underTest.appliesTo(project, metricEvaluationResult);

@@ -111,7 +111,7 @@ public class SmallChangesetQualityGateSpecialCaseTest {
public void should_not_change_green_conditions() {
QualityGateMeasuresStep.MetricEvaluationResult metricEvaluationResult = generateEvaluationResult(NEW_BUGS_KEY, OK);
Component project = generateNewRootProject();
measureRepository.addRawMeasure(PROJECT_REF, CoreMetrics.NEW_LINES_KEY, newMeasureBuilder().setVariation(19).create(1000));
measureRepository.addRawMeasure(PROJECT_REF, CoreMetrics.NEW_LINES_KEY, newMeasureBuilder().create(19));

boolean result = underTest.appliesTo(project, metricEvaluationResult);


+ 6
- 6
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectexport/steps/ExportLiveMeasuresStepTest.java View File

@@ -70,8 +70,8 @@ public class ExportLiveMeasuresStepTest {
public void export_measures() {
ComponentDto project = createProject(true);
componentRepository.register(1, project.uuid(), false);
MetricDto metric = dbTester.measures().insertMetric(m -> m.setValueType(INT.name()));
dbTester.measures().insertLiveMeasure(project, metric, m -> m.setValue(4711.0d).setVariation(null));
MetricDto metric = dbTester.measures().insertMetric(m -> m.setKey("metric1").setValueType(INT.name()));
dbTester.measures().insertLiveMeasure(project, metric, m -> m.setValue(4711.0d));
when(projectHolder.projectDto()).thenReturn(dbTester.components().getProjectDto(project));
when(projectHolder.branches()).thenReturn(newArrayList(new BranchDto()
.setProjectUuid(project.uuid())
@@ -131,8 +131,8 @@ public class ExportLiveMeasuresStepTest {
public void test_exported_fields() {
ComponentDto project = createProject(true);
componentRepository.register(1, project.uuid(), false);
MetricDto metric = dbTester.measures().insertMetric(m -> m.setValueType(INT.name()));
dbTester.measures().insertLiveMeasure(project, metric, m -> m.setProjectUuid(project.uuid()).setValue(4711.0d).setData("test").setVariation(7.0d));
MetricDto metric = dbTester.measures().insertMetric(m -> m.setKey("new_metric").setValueType(INT.name()));
dbTester.measures().insertLiveMeasure(project, metric, m -> m.setProjectUuid(project.uuid()).setValue(7.0d).setData("test"));
when(projectHolder.projectDto()).thenReturn(dbTester.components().getProjectDto(project));
when(projectHolder.branches()).thenReturn(newArrayList(new BranchDto()
.setProjectUuid(project.uuid())
@@ -154,7 +154,7 @@ public class ExportLiveMeasuresStepTest {
.containsOnly(tuple(
1L,
0,
4711.0d,
0.0d,
"test",
7.0d));
assertThat(logTester.logs(LoggerLevel.DEBUG)).contains("1 live measures exported");
@@ -166,7 +166,7 @@ public class ExportLiveMeasuresStepTest {
ComponentDto project = createProject(true);
componentRepository.register(1, project.uuid(), false);
MetricDto metric = dbTester.measures().insertMetric(m -> m.setValueType(INT.name()));
dbTester.measures().insertLiveMeasure(project, metric, m -> m.setProjectUuid(project.uuid()).setValue(null).setData((String) null).setVariation(null));
dbTester.measures().insertLiveMeasure(project, metric, m -> m.setProjectUuid(project.uuid()).setValue(null).setData((String) null));
when(projectHolder.projectDto()).thenReturn(dbTester.components().getProjectDto(project));
when(projectHolder.branches()).thenReturn(newArrayList(new BranchDto()
.setProjectUuid(project.uuid())

+ 34
- 4
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectexport/steps/ExportMeasuresStepTest.java View File

@@ -82,6 +82,12 @@ public class ExportMeasuresStepTest {
.setShortName("Coverage")
.setEnabled(false);

private static final MetricDto NEW_NCLOC = new MetricDto()
.setUuid("5")
.setKey("new_ncloc")
.setShortName("New Lines of code")
.setEnabled(true);

private static final List<BranchDto> BRANCHES = newArrayList(
new BranchDto()
.setBranchType(BranchType.BRANCH)
@@ -107,7 +113,7 @@ public class ExportMeasuresStepTest {
String projectUuid = dbTester.components().insertPublicProject(PROJECT).uuid();
componentRepository.register(1, projectUuid, false);
dbTester.getDbClient().componentDao().insert(dbTester.getSession(), FILE, ANOTHER_PROJECT);
dbTester.getDbClient().metricDao().insert(dbTester.getSession(), NCLOC, DISABLED_METRIC);
dbTester.getDbClient().metricDao().insert(dbTester.getSession(), NCLOC, DISABLED_METRIC, NEW_NCLOC);
dbTester.commit();
when(projectHolder.projectDto()).thenReturn(dbTester.components().getProjectDto(PROJECT));
when(projectHolder.branches()).thenReturn(BRANCHES);
@@ -174,8 +180,7 @@ public class ExportMeasuresStepTest {
.setValue(100.0)
.setData("data")
.setAlertStatus("OK")
.setAlertText("alert text")
.setVariation(1.0);
.setAlertText("alert text");
insertMeasure(analysis, PROJECT, dto);
dbTester.commit();

@@ -189,7 +194,32 @@ public class ExportMeasuresStepTest {
assertThat(measure.getTextValue()).isEqualTo(dto.getData());
assertThat(measure.getMetricRef()).isZero();
assertThat(measure.getAnalysisUuid()).isEqualTo(analysis.getUuid());
assertThat(measure.getVariation1().getValue()).isEqualTo(dto.getVariation());
assertThat(measure.getVariation1().getValue()).isZero();
}

@Test
public void test_exported_fields_new_metric() {
SnapshotDto analysis = insertSnapshot("U_1", PROJECT, STATUS_PROCESSED);
MeasureDto dto = new MeasureDto()
.setMetricUuid(NEW_NCLOC.getUuid())
.setValue(100.0)
.setData("data")
.setAlertStatus("OK")
.setAlertText("alert text");
insertMeasure(analysis, PROJECT, dto);
dbTester.commit();

underTest.execute(new TestComputationStepContext());

List<ProjectDump.Measure> exportedMeasures = dumpWriter.getWrittenMessagesOf(DumpElement.MEASURES);
ProjectDump.Measure measure = exportedMeasures.get(0);
assertThat(measure.getAlertStatus()).isEqualTo(dto.getAlertStatus());
assertThat(measure.getAlertText()).isEqualTo(dto.getAlertText());
assertThat(measure.getDoubleValue().getValue()).isZero();
assertThat(measure.getTextValue()).isEqualTo(dto.getData());
assertThat(measure.getMetricRef()).isZero();
assertThat(measure.getAnalysisUuid()).isEqualTo(analysis.getUuid());
assertThat(measure.getVariation1().getValue()).isEqualTo(dto.getValue());
}

@Test

+ 19
- 40
server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/measure/MeasureAssert.java View File

@@ -89,6 +89,25 @@ public class MeasureAssert extends AbstractAssert<MeasureAssert, Measure> {
return this;
}

public MeasureAssert hasValue(double expected, Offset<Double> offset) {
isNotNull();

if (actual.getValueType() != Measure.ValueType.DOUBLE) {
failWithMessage(
"Expected Measure to have a double value and therefore its ValueType to be <%s> but was <%s>",
Measure.ValueType.DOUBLE, actual.getValueType());
}

double value = actual.getDoubleValue();
if (abs(expected - value) > offset.value) {
failWithMessage(
"Expected value of Measure to be close to <%s> by less than <%s> but was <%s>",
expected, offset.value, value);
}

return this;
}

public MeasureAssert hasValue(boolean expected) {
isNotNull();

@@ -197,46 +216,6 @@ public class MeasureAssert extends AbstractAssert<MeasureAssert, Measure> {
}
}

public MeasureAssert hasVariation(double expected) {
isNotNull();
hasVariation();

if (!actual.hasVariation()) {
failWithMessage("Expected Measure to have a variation but it did not");
}

double variation = actual.getVariation();
if (variation != expected) {
failWithMessage("Expected variation of Measure to be <%s> but was <%s>", expected, variation);
}

return this;
}

public MeasureAssert hasVariation(double expected, Offset<Double> offset) {
isNotNull();
hasVariation();

if (!actual.hasVariation()) {
failWithMessage("Expected Measure to have a variation but it did not");
}

double variation = actual.getVariation();
if (abs(expected - variation) > offset.value) {
failWithMessage(
"Expected variation of Measure to be close to <%s> by less than <%s> but was <%s>",
expected, offset.value, variation);
}

return this;
}

private void hasVariation() {
if (!actual.hasVariation()) {
failWithMessage("Expected Measure to have a variation but it did not");
}
}

public void isAbsent() {
if (actual != null) {
failWithMessage("Expected measure to be absent");

+ 0
- 15
server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/measure/MeasureRepoEntry.java View File

@@ -19,8 +19,6 @@
*/
package org.sonar.ce.task.projectanalysis.measure;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
@@ -73,7 +71,6 @@ public final class MeasureRepoEntry {
public static boolean deepEquals(Measure measure, Measure measure1) {
return measure.getValueType() == measure1.getValueType()
&& equalsByValue(measure, measure1)
&& equalsByVariation(measure, measure1)
&& equalsByQualityGateStatus(measure, measure1)
&& Objects.equals(measure.getData(), measure1.getData());
}
@@ -99,18 +96,6 @@ public final class MeasureRepoEntry {
}
}

private static boolean equalsByVariation(Measure measure, Measure measure1) {
return measure.hasVariation() == measure1.hasVariation() && (!measure.hasVariation()
|| Double.compare(scale(measure.getVariation()), scale(measure1.getVariation())) == 0);
}

private static final int DOUBLE_PRECISION = 1;

private static double scale(double value) {
BigDecimal bd = BigDecimal.valueOf(value);
return bd.setScale(DOUBLE_PRECISION, RoundingMode.HALF_UP).doubleValue();
}

private static boolean equalsByQualityGateStatus(Measure measure, Measure measure1) {
if (measure.hasQualityGateStatus() != measure1.hasQualityGateStatus()) {
return false;

+ 0
- 13
server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDto.java View File

@@ -44,8 +44,6 @@ public class LiveMeasureDto {
private String textValue;
@Nullable
private byte[] data;
@Nullable
private Double variation;

void setUuidForUpsert(@Nullable String s) {
this.uuidForUpsert = s;
@@ -126,16 +124,6 @@ public class LiveMeasureDto {
return this;
}

@CheckForNull
public Double getVariation() {
return variation;
}

public LiveMeasureDto setVariation(@Nullable Double variation) {
this.variation = variation;
return this;
}

@Override
public String toString() {
StringBuilder sb = new StringBuilder("LiveMeasureDto{");
@@ -143,7 +131,6 @@ public class LiveMeasureDto {
sb.append(", projectUuid='").append(projectUuid).append('\'');
sb.append(", metricUuid=").append(metricUuid);
sb.append(", value=").append(value);
sb.append(", variation=").append(variation);
sb.append(", textValue='").append(textValue).append('\'');
sb.append(", data=").append(Arrays.toString(data));
sb.append('}');

+ 0
- 12
server/sonar-db-dao/src/main/java/org/sonar/db/measure/MeasureDto.java View File

@@ -31,7 +31,6 @@ public class MeasureDto {
private Double value;
private String textValue;
private byte[] dataValue;
private Double variation;
private String alertStatus;
private String alertText;
private String componentUuid;
@@ -88,16 +87,6 @@ public class MeasureDto {
return this;
}

@CheckForNull
public Double getVariation() {
return variation;
}

public MeasureDto setVariation(@Nullable Double d) {
variation = d;
return this;
}

@CheckForNull
public String getAlertStatus() {
return alertStatus;
@@ -142,7 +131,6 @@ public class MeasureDto {
.add("value", value)
.add("textValue", textValue)
.add("dataValue", dataValue)
.add("variation", variation)
.add("alertStatus", alertStatus)
.add("alertText", alertText)
.add("componentUuid", componentUuid)

+ 6
- 7
server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMeasuresIndexerIterator.java View File

@@ -79,18 +79,18 @@ public class ProjectMeasuresIndexerIterator extends CloseableIterator<ProjectMea

private static final String PROJECT_FILTER = " AND p.uuid=?";

private static final String SQL_MEASURES = "SELECT m.name, pm.value, pm.variation, pm.text_value FROM live_measures pm " +
private static final String SQL_MEASURES = "SELECT m.name, pm.value, pm.text_value FROM live_measures pm " +
"INNER JOIN metrics m ON m.uuid = pm.metric_uuid " +
"WHERE pm.component_uuid = ? " +
"AND m.name IN ({metricNames}) " +
"AND (pm.value IS NOT NULL OR pm.variation IS NOT NULL OR pm.text_value IS NOT NULL) " +
"AND (pm.value IS NOT NULL OR pm.text_value IS NOT NULL) " +
"AND m.enabled = ? ";

private static final String SQL_NCLOC_LANGUAGE_DISTRIBUTION = "SELECT m.name, pm.value, pm.variation, pm.text_value FROM live_measures pm " +
private static final String SQL_NCLOC_LANGUAGE_DISTRIBUTION = "SELECT m.name, pm.value, pm.text_value FROM live_measures pm " +
"INNER JOIN metrics m ON m.uuid = pm.metric_uuid " +
"WHERE pm.component_uuid = ? " +
"AND m.name = ? " +
"AND (pm.value IS NOT NULL OR pm.variation IS NOT NULL OR pm.text_value IS NOT NULL) " +
"AND (pm.value IS NOT NULL OR pm.text_value IS NOT NULL) " +
"AND m.enabled = ? ";

private static final String SQL_PROJECT_BRANCHES = "SELECT uuid FROM project_branches pb " +
@@ -109,8 +109,7 @@ public class ProjectMeasuresIndexerIterator extends CloseableIterator<ProjectMea
private static final boolean ENABLED = true;
private static final int FIELD_METRIC_NAME = 1;
private static final int FIELD_MEASURE_VALUE = 2;
private static final int FIELD_MEASURE_VARIATION = 3;
private static final int FIELD_MEASURE_TEXT_VALUE = 4;
private static final int FIELD_MEASURE_TEXT_VALUE = 3;

private final DbSession dbSession;
private final PreparedStatement measuresStatement;
@@ -310,7 +309,7 @@ public class ProjectMeasuresIndexerIterator extends CloseableIterator<ProjectMea

private static void readMeasure(ResultSet rs, Measures measures) throws SQLException {
String metricKey = rs.getString(FIELD_METRIC_NAME);
Optional<Double> value = metricKey.startsWith("new_") ? getDouble(rs, FIELD_MEASURE_VARIATION) : getDouble(rs, FIELD_MEASURE_VALUE);
Optional<Double> value = getDouble(rs, FIELD_MEASURE_VALUE);
if (value.isPresent()) {
measures.addNumericMeasure(metricKey, value.get());
return;

+ 1
- 9
server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml View File

@@ -9,8 +9,7 @@
lm.metric_uuid as metricUuid,
lm.value as value,
lm.text_value as textValue,
lm.measure_data as data,
lm.variation as variation
lm.measure_data as data
</sql>

<select id="selectByComponentUuidsAndMetricUuids" parameterType="map" resultType="org.sonar.db.measure.LiveMeasureDto">
@@ -118,7 +117,6 @@
metric_uuid,
value,
text_value,
variation,
measure_data,
created_at,
updated_at
@@ -129,7 +127,6 @@
#{dto.metricUuid, jdbcType=VARCHAR},
#{dto.value, jdbcType=DOUBLE},
#{dto.textValue, jdbcType=VARCHAR},
#{dto.variation, jdbcType=DOUBLE},
#{dto.data, jdbcType=BINARY},
#{now, jdbcType=BIGINT},
#{now, jdbcType=BIGINT}
@@ -139,7 +136,6 @@
<update id="update" parameterType="map">
update live_measures set
value = #{dto.value, jdbcType=DOUBLE},
variation = #{dto.variation, jdbcType=DOUBLE},
text_value = #{dto.textValue, jdbcType=VARCHAR},
measure_data = #{dto.data, jdbcType=BINARY},
updated_at = #{now, jdbcType=BIGINT}
@@ -162,7 +158,6 @@
metric_uuid,
value,
text_value,
variation,
measure_data,
created_at,
updated_at
@@ -173,20 +168,17 @@
#{dto.metricUuid, jdbcType=VARCHAR},
#{dto.value, jdbcType=DOUBLE},
#{dto.textValue, jdbcType=VARCHAR},
#{dto.variation, jdbcType=DOUBLE},
#{dto.data, jdbcType=BINARY},
#{now, jdbcType=BIGINT},
#{now, jdbcType=BIGINT}
)
on conflict(component_uuid, metric_uuid) do update set
value = excluded.value,
variation = excluded.variation,
text_value = excluded.text_value,
measure_data = excluded.measure_data,
updated_at = excluded.updated_at
where
live_measures.value is distinct from excluded.value or
live_measures.variation is distinct from excluded.variation or
live_measures.text_value is distinct from excluded.text_value or
live_measures.measure_data is distinct from excluded.measure_data
</update>

+ 1
- 4
server/sonar-db-dao/src/main/resources/org/sonar/db/measure/MeasureMapper.xml View File

@@ -12,8 +12,7 @@
pm.text_value as textValue,
pm.alert_status as alertStatus,
pm.alert_text as alertText,
pm.measure_data as dataValue,
pm.variation_value_1 as variation
pm.measure_data as dataValue
</sql>

<select id="selectLastMeasure" parameterType="map" resultType="Measure">
@@ -106,7 +105,6 @@
text_value,
alert_status,
alert_text,
variation_value_1,
measure_data)
VALUES (
#{uuid, jdbcType=VARCHAR},
@@ -117,7 +115,6 @@
#{textValue, jdbcType=VARCHAR},
#{alertStatus, jdbcType=VARCHAR},
#{alertText, jdbcType=VARCHAR},
#{variation, jdbcType=DOUBLE},
#{dataValue, jdbcType=BINARY}
)
</insert>

+ 0
- 2
server/sonar-db-dao/src/schema/schema-sq.ddl View File

@@ -446,7 +446,6 @@ CREATE TABLE "LIVE_MEASURES"(
"METRIC_UUID" CHARACTER VARYING(40) NOT NULL,
"VALUE" DOUBLE PRECISION,
"TEXT_VALUE" CHARACTER VARYING(4000),
"VARIATION" DOUBLE PRECISION,
"MEASURE_DATA" BINARY LARGE OBJECT,
"UPDATE_MARKER" CHARACTER VARYING(40),
"CREATED_AT" BIGINT NOT NULL,
@@ -690,7 +689,6 @@ CREATE TABLE "PROJECT_MEASURES"(
"ALERT_STATUS" CHARACTER VARYING(5),
"ALERT_TEXT" CHARACTER VARYING(4000),
"PERSON_ID" INTEGER,
"VARIATION_VALUE_1" DOUBLE PRECISION,
"MEASURE_DATA" BINARY LARGE OBJECT,
"METRIC_UUID" CHARACTER VARYING(40) NOT NULL
);

+ 4
- 54
server/sonar-db-dao/src/test/java/org/sonar/db/measure/LiveMeasureDaoTest.java View File

@@ -291,14 +291,14 @@ public class LiveMeasureDaoTest {
MetricDto metric = db.measures().insertMetric();
ComponentDto project = db.components().insertPrivateProject();
ComponentDto file = db.components().insertComponent(newFileDto(project));
underTest.insert(db.getSession(), newLiveMeasure(file, metric).setValue(3.14).setVariation(0.1).setData("text_value"));
underTest.insert(db.getSession(), newLiveMeasure(file, metric).setValue(3.14).setData("text_value"));

LiveMeasureDto result = underTest.selectMeasure(db.getSession(), file.uuid(), metric.getKey()).orElseThrow(() -> new IllegalArgumentException("Measure not found"));

assertThat(result).as("Fail to map fields of %s", result.toString()).extracting(
LiveMeasureDto::getProjectUuid, LiveMeasureDto::getComponentUuid, LiveMeasureDto::getMetricUuid, LiveMeasureDto::getValue, LiveMeasureDto::getVariation,
LiveMeasureDto::getProjectUuid, LiveMeasureDto::getComponentUuid, LiveMeasureDto::getMetricUuid, LiveMeasureDto::getValue,
LiveMeasureDto::getDataAsString, LiveMeasureDto::getTextValue)
.contains(project.uuid(), file.uuid(), metric.getUuid(), 3.14, 0.1, "text_value", "text_value");
.contains(project.uuid(), file.uuid(), metric.getUuid(), 3.14, "text_value", "text_value");
}

@Test
@@ -403,7 +403,6 @@ public class LiveMeasureDaoTest {

// update
dto.setValue(dto.getValue() + 1);
dto.setVariation(dto.getVariation() + 10);
dto.setData(dto.getDataAsString() + "_new");
underTest.insertOrUpdate(db.getSession(), dto);
verifyPersisted(dto);
@@ -491,7 +490,6 @@ public class LiveMeasureDaoTest {

// update
dto.setValue(dto.getValue() + 1);
dto.setVariation(dto.getVariation() + 10);
dto.setData(dto.getDataAsString() + "_new");
count = underTest.upsert(db.getSession(), dto);
assertThat(count).isOne();
@@ -564,54 +562,6 @@ public class LiveMeasureDaoTest {
verifyTableSize(1);
}

@Test
public void upsert_updates_row_if_variation_is_changed() {
if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) {
return;
}
LiveMeasureDto dto = newLiveMeasure().setVariation(40.0);
underTest.upsert(db.getSession(), dto);

// update
dto.setVariation(50.0);
int count = underTest.upsert(db.getSession(), dto);
assertThat(count).isOne();
verifyPersisted(dto);
verifyTableSize(1);
}

@Test
public void upsert_updates_row_if_variation_is_removed() {
if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) {
return;
}
LiveMeasureDto dto = newLiveMeasure().setVariation(40.0);
underTest.upsert(db.getSession(), dto);

// update
dto.setVariation(null);
int count = underTest.upsert(db.getSession(), dto);
assertThat(count).isOne();
verifyPersisted(dto);
verifyTableSize(1);
}

@Test
public void upsert_updates_row_if_variation_is_added() {
if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) {
return;
}
LiveMeasureDto dto = newLiveMeasure().setVariation(null);
underTest.upsert(db.getSession(), dto);

// update
dto.setVariation(40.0);
int count = underTest.upsert(db.getSession(), dto);
assertThat(count).isOne();
verifyPersisted(dto);
verifyTableSize(1);
}

@Test
public void upsert_updates_row_if_value_is_changed() {
if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) {
@@ -698,7 +648,7 @@ public class LiveMeasureDaoTest {
assertThat(selected).hasSize(1);
assertThat(selected.get(0)).isEqualToComparingOnlyGivenFields(dto,
// do not compare the field "uuid", which is used only for insert, not select
"componentUuid", "projectUuid", "metricUuid", "value", "textValue", "data", "variation");
"componentUuid", "projectUuid", "metricUuid", "value", "textValue", "data");
}

private void setupProjectsWithLoc() {

+ 1
- 4
server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDtoTest.java View File

@@ -32,12 +32,9 @@ public class MeasureDtoTest {
public void test_getter_and_setter() {
underTest
.setValue(2d)
.setData("text value")
.setVariation(1d);

.setData("text value");
assertThat(underTest.getValue()).isEqualTo(2d);
assertThat(underTest.getData()).isNotNull();
assertThat(underTest.getVariation()).isEqualTo(1d);
}

@Test

+ 4
- 4
server/sonar-db-dao/src/test/java/org/sonar/db/measure/ProjectMeasuresIndexerIteratorTest.java View File

@@ -113,7 +113,7 @@ public class ProjectMeasuresIndexerIteratorTest {
c -> c.setKey("Project-Key").setName("Project Name"),
p -> p.setTagsString("platform,java"));
MetricDto metric = dbTester.measures().insertMetric(m -> m.setValueType(INT.name()).setKey("new_lines"));
dbTester.measures().insertLiveMeasure(project, metric, m -> m.setVariation(10d));
dbTester.measures().insertLiveMeasure(project, metric, m -> m.setValue(10d));

Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById();

@@ -139,7 +139,7 @@ public class ProjectMeasuresIndexerIteratorTest {
public void does_not_fail_when_quality_gate_has_no_value() {
ComponentDto project = dbTester.components().insertPrivateProject();
MetricDto metric = dbTester.measures().insertMetric(m -> m.setValueType(LEVEL.name()).setKey("alert_status"));
dbTester.measures().insertLiveMeasure(project, metric, m -> m.setValue(null).setVariation(null).setData((String) null));
dbTester.measures().insertLiveMeasure(project, metric, m -> m.setValue(null).setData((String) null));

Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById();

@@ -210,8 +210,8 @@ public class ProjectMeasuresIndexerIteratorTest {
ComponentDto project = dbTester.components().insertPrivateProject();

dbTester.measures().insertLiveMeasure(project, metric1, m -> m.setValue(10d));
dbTester.measures().insertLiveMeasure(project, leakMetric, m -> m.setValue(null).setVariation(20d));
dbTester.measures().insertLiveMeasure(project, metric2, m -> m.setValue(null).setVariation(null));
dbTester.measures().insertLiveMeasure(project, leakMetric, m -> m.setValue(20d));
dbTester.measures().insertLiveMeasure(project, metric2, m -> m.setValue(null));

Map<String, Double> numericMeasures = createResultSetAndReturnDocsById().get(project.uuid()).getMeasures().getNumericMeasures();
assertThat(numericMeasures).containsOnly(entry(metric1.getKey(), 10d), entry(leakMetric.getKey(), 20d));

+ 2
- 4
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureTesting.java View File

@@ -62,8 +62,7 @@ public class MeasureTesting {
.setComponentUuid(String.valueOf(cursor++))
.setProjectUuid(String.valueOf(cursor++))
.setData(String.valueOf(cursor++))
.setValue((double) cursor++)
.setVariation((double) cursor++);
.setValue((double) cursor++);
}

public static LiveMeasureDto newLiveMeasure(ComponentDto component, MetricDto metric) {
@@ -72,7 +71,6 @@ public class MeasureTesting {
.setComponentUuid(component.uuid())
.setProjectUuid(component.branchUuid())
.setData(String.valueOf(cursor++))
.setValue((double) cursor++)
.setVariation((double) cursor++);
.setValue((double) cursor++);
}
}

+ 2
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java View File

@@ -36,6 +36,7 @@ import org.sonar.server.platform.db.migration.version.v94.DbVersion94;
import org.sonar.server.platform.db.migration.version.v95.DbVersion95;
import org.sonar.server.platform.db.migration.version.v96.DbVersion96;
import org.sonar.server.platform.db.migration.version.v97.DbVersion97;
import org.sonar.server.platform.db.migration.version.v98.DbVersion98;

public class MigrationConfigurationModule extends Module {
@Override
@@ -52,6 +53,7 @@ public class MigrationConfigurationModule extends Module {
DbVersion95.class,
DbVersion96.class,
DbVersion97.class,
DbVersion98.class,

// migration steps
MigrationStepRegistryImpl.class,

+ 35
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v98/DbVersion98.java View File

@@ -0,0 +1,35 @@
/*
* SonarQube
* Copyright (C) 2009-2022 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v98;

import org.sonar.server.platform.db.migration.step.MigrationStepRegistry;
import org.sonar.server.platform.db.migration.version.DbVersion;

public class DbVersion98 implements DbVersion {
@Override
public void addSteps(MigrationStepRegistry registry) {
registry
.add(6700, "Move live measure variations to values", MoveLiveMeasureVariationToValue.class)
.add(6701, "Drop live measure variation column", DropLiveMeasureVariationColumn.class)
.add(6702, "Move project measure variations to values", MoveProjectMeasureVariationToValue.class)
.add(6703, "Drop project measure variation column", DropProjectMeasureVariationColumn.class)
;
}
}

+ 33
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v98/DropLiveMeasureVariationColumn.java View File

@@ -0,0 +1,33 @@
/*
* SonarQube
* Copyright (C) 2009-2022 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v98;

import org.sonar.db.Database;
import org.sonar.server.platform.db.migration.step.DropColumnChange;

public class DropLiveMeasureVariationColumn extends DropColumnChange {

public static final String TABLE_NAME = "live_measures";
public static final String COLUMN_NAME = "variation";

public DropLiveMeasureVariationColumn(Database db) {
super(db, TABLE_NAME, COLUMN_NAME);
}
}

+ 33
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v98/DropProjectMeasureVariationColumn.java View File

@@ -0,0 +1,33 @@
/*
* SonarQube
* Copyright (C) 2009-2022 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v98;

import org.sonar.db.Database;
import org.sonar.server.platform.db.migration.step.DropColumnChange;

public class DropProjectMeasureVariationColumn extends DropColumnChange {

public static final String TABLE_NAME = "project_measures";
public static final String COLUMN_NAME = "variation_value_1";

public DropProjectMeasureVariationColumn(Database db) {
super(db, TABLE_NAME, COLUMN_NAME);
}
}

+ 28
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v98/MoveLiveMeasureVariationToValue.java View File

@@ -0,0 +1,28 @@
/*
* SonarQube
* Copyright (C) 2009-2022 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v98;

import org.sonar.db.Database;

public class MoveLiveMeasureVariationToValue extends VariationMigration {
public MoveLiveMeasureVariationToValue(Database db) {
super(db, "live_measures", "variation");
}
}

+ 28
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v98/MoveProjectMeasureVariationToValue.java View File

@@ -0,0 +1,28 @@
/*
* SonarQube
* Copyright (C) 2009-2022 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v98;

import org.sonar.db.Database;

public class MoveProjectMeasureVariationToValue extends VariationMigration {
public MoveProjectMeasureVariationToValue(Database db) {
super(db, "project_measures", "variation_value_1");
}
}

+ 65
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v98/VariationMigration.java View File

@@ -0,0 +1,65 @@
/*
* SonarQube
* Copyright (C) 2009-2022 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v98;

import java.sql.SQLException;
import org.sonar.db.Database;
import org.sonar.db.DatabaseUtils;
import org.sonar.server.platform.db.migration.step.DataChange;
import org.sonar.server.platform.db.migration.step.MassUpdate;

public class VariationMigration extends DataChange {
private final String tableName;
private final String variationColumnName;

public VariationMigration(Database db, String tableName, String variationColumnName) {
super(db);
this.tableName = tableName;
this.variationColumnName = variationColumnName;
}

@Override
protected void execute(DataChange.Context context) throws SQLException {
if (columnExists()) {
migrateVariation(context,
"select uuid, " + variationColumnName + " from " + tableName + " where " + variationColumnName + " is not null and value is null",
"update " + tableName + " set value = ? where uuid = ?");
}
}

static void migrateVariation(DataChange.Context context, String selectQuery, String updateQuery) throws SQLException {
MassUpdate massUpdate = context.prepareMassUpdate();
massUpdate.select(selectQuery);
massUpdate.update(updateQuery);
massUpdate.execute((row, update) -> {
String uuid = row.getString(1);
double variation = row.getDouble(2);
update.setDouble(1, variation);
update.setString(2, uuid);
return true;
});
}

private boolean columnExists() throws SQLException {
try (var connection = getDatabase().getDataSource().getConnection()) {
return DatabaseUtils.tableColumnExists(connection, tableName, variationColumnName);
}
}
}

+ 42
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v98/DbVersion98Test.java View File

@@ -0,0 +1,42 @@
/*
* SonarQube
* Copyright (C) 2009-2022 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v98;

import org.junit.Test;
import org.sonar.server.platform.db.migration.version.v97.DbVersion97;

import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationNotEmpty;
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMinimumMigrationNumber;

public class DbVersion98Test {

private final DbVersion98 underTest = new DbVersion98();

@Test
public void migrationNumber_starts_at_6600() {
verifyMinimumMigrationNumber(underTest, 6700);
}

@Test
public void verify_migration_is_not_empty() {
verifyMigrationNotEmpty(underTest);
}

}

+ 53
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v98/DropLiveMeasureVariationColumnTest.java View File

@@ -0,0 +1,53 @@
/*
* SonarQube
* Copyright (C) 2009-2022 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v98;

import java.sql.SQLException;
import java.sql.Types;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.db.CoreDbTester;
import org.sonar.server.platform.db.migration.step.DdlChange;

public class DropLiveMeasureVariationColumnTest {
private static final String COLUMN_NAME = "variation";
private static final String TABLE_NAME = "live_measures";

@Rule
public final CoreDbTester db = CoreDbTester.createForSchema(DropLiveMeasureVariationColumnTest.class, "schema.sql");

private final DdlChange dropColumn = new DropLiveMeasureVariationColumn(db.database());

@Test
public void migration_should_drop_action_plan_column() throws SQLException {
db.assertColumnDefinition(TABLE_NAME, COLUMN_NAME, Types.DOUBLE, null, true);
dropColumn.execute();
db.assertColumnDoesNotExist(TABLE_NAME, COLUMN_NAME);
}

@Test
public void migration_should_be_reentrant() throws SQLException {
db.assertColumnDefinition(TABLE_NAME, COLUMN_NAME, Types.DOUBLE, null, true);
dropColumn.execute();
// re-entrant
dropColumn.execute();
db.assertColumnDoesNotExist(TABLE_NAME, COLUMN_NAME);
}
}

+ 53
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v98/DropProjectMeasureVariationColumnTest.java View File

@@ -0,0 +1,53 @@
/*
* SonarQube
* Copyright (C) 2009-2022 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v98;

import java.sql.SQLException;
import java.sql.Types;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.db.CoreDbTester;
import org.sonar.server.platform.db.migration.step.DdlChange;

public class DropProjectMeasureVariationColumnTest {
private static final String COLUMN_NAME = "variation_value_1";
private static final String TABLE_NAME = "project_measures";

@Rule
public final CoreDbTester db = CoreDbTester.createForSchema(DropProjectMeasureVariationColumnTest.class, "schema.sql");

private final DdlChange dropColumn = new DropProjectMeasureVariationColumn(db.database());

@Test
public void migration_should_drop_action_plan_column() throws SQLException {
db.assertColumnDefinition(TABLE_NAME, COLUMN_NAME, Types.DOUBLE, null, true);
dropColumn.execute();
db.assertColumnDoesNotExist(TABLE_NAME, COLUMN_NAME);
}

@Test
public void migration_should_be_reentrant() throws SQLException {
db.assertColumnDefinition(TABLE_NAME, COLUMN_NAME, Types.DOUBLE, null, true);
dropColumn.execute();
// re-entrant
dropColumn.execute();
db.assertColumnDoesNotExist(TABLE_NAME, COLUMN_NAME);
}
}

+ 80
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v98/MoveLiveMeasureVariationToValueTest.java View File

@@ -0,0 +1,80 @@
/*
* SonarQube
* Copyright (C) 2009-2022 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v98;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.db.CoreDbTester;
import org.sonar.server.platform.db.migration.step.DataChange;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;

public class MoveLiveMeasureVariationToValueTest {
private static final String TABLE = "live_measures";
private int counter = 0;

@Rule
public final CoreDbTester db = CoreDbTester.createForSchema(MoveLiveMeasureVariationToValueTest.class, "schema.sql");

private final DataChange underTest = new MoveLiveMeasureVariationToValue(db.database());

@Test
public void moves_value_to_value_if_value_is_null() throws SQLException {
insertMeasure("1", null, 1000D);
insertMeasure("2", null, 2000D);

underTest.execute();

List<Map<String, Object>> select = db.select("select uuid as \"UUID\", value as \"VALUE\", variation as \"VARIATION\" from live_measures");
assertThat(select)
.extracting(t -> t.get("UUID"), t -> t.get("VALUE"), t -> t.get("VARIATION"))
.containsOnly(tuple("1", 1000D, 1000D), tuple("2", 2000D, 2000D));
}

@Test
public void does_not_move_if_row_contains_value() throws SQLException {
insertMeasure("1", 1100D, 1000D);
insertMeasure("2", 2100D, 2000D);

underTest.execute();

List<Map<String, Object>> select = db.select("select uuid as \"UUID\", value as \"VALUE\", variation as \"VARIATION\" from live_measures");
assertThat(select)
.extracting(t -> t.get("UUID"), t -> t.get("VALUE"), t -> t.get("VARIATION"))
.containsOnly(tuple("1", 1100D, 1000D), tuple("2", 2100D, 2000D));
}

private void insertMeasure(String uuid, @Nullable Double value, @Nullable Double variation) {
db.executeInsert(TABLE,
"uuid", uuid,
"project_uuid", "p1",
"component_uuid", "c1",
"metric_uuid", counter++,
"value", value,
"variation", variation,
"created_at", counter++,
"updated_at", counter++);
}
}

+ 78
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v98/MoveProjectMeasureVariationToValueTest.java View File

@@ -0,0 +1,78 @@
/*
* SonarQube
* Copyright (C) 2009-2022 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v98;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.db.CoreDbTester;
import org.sonar.server.platform.db.migration.step.DataChange;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;

public class MoveProjectMeasureVariationToValueTest {
private static final String TABLE = "project_measures";
private int counter = 0;

@Rule
public final CoreDbTester db = CoreDbTester.createForSchema(MoveProjectMeasureVariationToValueTest.class, "schema.sql");

private final DataChange underTest = new MoveProjectMeasureVariationToValue(db.database());

@Test
public void moves_value_to_value_if_value_is_null() throws SQLException {
insertMeasure("1", null, 1000D);
insertMeasure("2", null, 2000D);

underTest.execute();

List<Map<String, Object>> select = db.select("select uuid as \"UUID\", value as \"VALUE\", variation_value_1 as \"VARIATION\" from project_measures");
assertThat(select)
.extracting(t -> t.get("UUID"), t -> t.get("VALUE"), t -> t.get("VARIATION"))
.containsOnly(tuple("1", 1000D, 1000D), tuple("2", 2000D, 2000D));
}

@Test
public void does_not_move_if_row_contains_value() throws SQLException {
insertMeasure("1", 1100D, 1000D);
insertMeasure("2", 2100D, 2000D);

underTest.execute();

List<Map<String, Object>> select = db.select("select uuid as \"UUID\", value as \"VALUE\", variation_value_1 as \"VARIATION\" from project_measures");
assertThat(select)
.extracting(t -> t.get("UUID"), t -> t.get("VALUE"), t -> t.get("VARIATION"))
.containsOnly(tuple("1", 1100D, 1000D), tuple("2", 2100D, 2000D));
}

private void insertMeasure(String uuid, @Nullable Double value, @Nullable Double variation) {
db.executeInsert(TABLE,
"uuid", uuid,
"analysis_uuid", "a1",
"component_uuid", "c1",
"metric_uuid", counter++,
"value", value,
"variation_value_1", variation);
}
}

+ 16
- 0
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v98/DropLiveMeasureVariationColumnTest/schema.sql View File

@@ -0,0 +1,16 @@
CREATE TABLE "LIVE_MEASURES"(
"UUID" CHARACTER VARYING(40) NOT NULL,
"PROJECT_UUID" CHARACTER VARYING(50) NOT NULL,
"COMPONENT_UUID" CHARACTER VARYING(50) NOT NULL,
"METRIC_UUID" CHARACTER VARYING(40) NOT NULL,
"VALUE" DOUBLE PRECISION,
"TEXT_VALUE" CHARACTER VARYING(4000),
"VARIATION" DOUBLE PRECISION,
"MEASURE_DATA" BINARY LARGE OBJECT,
"UPDATE_MARKER" CHARACTER VARYING(40),
"CREATED_AT" BIGINT NOT NULL,
"UPDATED_AT" BIGINT NOT NULL
);
ALTER TABLE "LIVE_MEASURES" ADD CONSTRAINT "PK_LIVE_MEASURES" PRIMARY KEY("UUID");
CREATE INDEX "LIVE_MEASURES_PROJECT" ON "LIVE_MEASURES"("PROJECT_UUID" NULLS FIRST);
CREATE UNIQUE INDEX "LIVE_MEASURES_COMPONENT" ON "LIVE_MEASURES"("COMPONENT_UUID" NULLS FIRST, "METRIC_UUID" NULLS FIRST);

+ 17
- 0
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v98/DropProjectMeasureVariationColumnTest/schema.sql View File

@@ -0,0 +1,17 @@
CREATE TABLE "PROJECT_MEASURES"(
"UUID" CHARACTER VARYING(40) NOT NULL,
"VALUE" DOUBLE PRECISION,
"ANALYSIS_UUID" CHARACTER VARYING(50) NOT NULL,
"COMPONENT_UUID" CHARACTER VARYING(50) NOT NULL,
"TEXT_VALUE" CHARACTER VARYING(4000),
"ALERT_STATUS" CHARACTER VARYING(5),
"ALERT_TEXT" CHARACTER VARYING(4000),
"PERSON_ID" INTEGER,
"VARIATION_VALUE_1" DOUBLE PRECISION,
"MEASURE_DATA" BINARY LARGE OBJECT,
"METRIC_UUID" CHARACTER VARYING(40) NOT NULL
);
ALTER TABLE "PROJECT_MEASURES" ADD CONSTRAINT "PK_PROJECT_MEASURES" PRIMARY KEY("UUID");
CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES"("COMPONENT_UUID" NULLS FIRST);
CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES"("ANALYSIS_UUID" NULLS FIRST, "METRIC_UUID" NULLS FIRST);
CREATE INDEX "PROJECT_MEASURES_METRIC" ON "PROJECT_MEASURES"("METRIC_UUID" NULLS FIRST);

+ 16
- 0
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v98/MoveLiveMeasureVariationToValueTest/schema.sql View File

@@ -0,0 +1,16 @@
CREATE TABLE "LIVE_MEASURES"(
"UUID" CHARACTER VARYING(40) NOT NULL,
"PROJECT_UUID" CHARACTER VARYING(50) NOT NULL,
"COMPONENT_UUID" CHARACTER VARYING(50) NOT NULL,
"METRIC_UUID" CHARACTER VARYING(40) NOT NULL,
"VALUE" DOUBLE PRECISION,
"TEXT_VALUE" CHARACTER VARYING(4000),
"VARIATION" DOUBLE PRECISION,
"MEASURE_DATA" BINARY LARGE OBJECT,
"UPDATE_MARKER" CHARACTER VARYING(40),
"CREATED_AT" BIGINT NOT NULL,
"UPDATED_AT" BIGINT NOT NULL
);
ALTER TABLE "LIVE_MEASURES" ADD CONSTRAINT "PK_LIVE_MEASURES" PRIMARY KEY("UUID");
CREATE INDEX "LIVE_MEASURES_PROJECT" ON "LIVE_MEASURES"("PROJECT_UUID" NULLS FIRST);
CREATE UNIQUE INDEX "LIVE_MEASURES_COMPONENT" ON "LIVE_MEASURES"("COMPONENT_UUID" NULLS FIRST, "METRIC_UUID" NULLS FIRST);

+ 17
- 0
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v98/MoveProjectMeasureVariationToValueTest/schema.sql View File

@@ -0,0 +1,17 @@
CREATE TABLE "PROJECT_MEASURES"(
"UUID" CHARACTER VARYING(40) NOT NULL,
"VALUE" DOUBLE PRECISION,
"ANALYSIS_UUID" CHARACTER VARYING(50) NOT NULL,
"COMPONENT_UUID" CHARACTER VARYING(50) NOT NULL,
"TEXT_VALUE" CHARACTER VARYING(4000),
"ALERT_STATUS" CHARACTER VARYING(5),
"ALERT_TEXT" CHARACTER VARYING(4000),
"PERSON_ID" INTEGER,
"VARIATION_VALUE_1" DOUBLE PRECISION,
"MEASURE_DATA" BINARY LARGE OBJECT,
"METRIC_UUID" CHARACTER VARYING(40) NOT NULL
);
ALTER TABLE "PROJECT_MEASURES" ADD CONSTRAINT "PK_PROJECT_MEASURES" PRIMARY KEY("UUID");
CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES"("COMPONENT_UUID" NULLS FIRST);
CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES"("ANALYSIS_UUID" NULLS FIRST, "METRIC_UUID" NULLS FIRST);
CREATE INDEX "PROJECT_MEASURES_METRIC" ON "PROJECT_MEASURES"("METRIC_UUID" NULLS FIRST);

+ 1
- 1
server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/ConditionEvaluator.java View File

@@ -121,7 +121,7 @@ class ConditionEvaluator {
@CheckForNull
private static Comparable getLeakValue(QualityGateEvaluator.Measure measure) {
if (NUMERICAL_TYPES.contains(measure.getType())) {
return measure.getNewMetricValue().isPresent() ? getNumericValue(measure.getType(), measure.getNewMetricValue().getAsDouble()) : null;
return measure.getValue().isPresent() ? getNumericValue(measure.getType(), measure.getValue().getAsDouble()) : null;
}

throw new IllegalArgumentException("Condition on leak period is not allowed for type " + measure.getType());

+ 0
- 2
server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/QualityGateEvaluator.java View File

@@ -55,7 +55,5 @@ public interface QualityGateEvaluator {
OptionalDouble getValue();

Optional<String> getStringValue();

OptionalDouble getNewMetricValue();
}
}

+ 2
- 2
server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/QualityGateEvaluatorImpl.java View File

@@ -83,8 +83,8 @@ public class QualityGateEvaluatorImpl implements QualityGateEvaluator {
private static boolean isSmallChangeset(Measures measures) {
Optional<Measure> newLines = measures.get(CoreMetrics.NEW_LINES_KEY);
return newLines.isPresent() &&
newLines.get().getNewMetricValue().isPresent() &&
newLines.get().getNewMetricValue().getAsDouble() < MAXIMUM_NEW_LINES_FOR_SMALL_CHANGESETS;
newLines.get().getValue().isPresent() &&
newLines.get().getValue().getAsDouble() < MAXIMUM_NEW_LINES_FOR_SMALL_CHANGESETS;
}

private static Level overallStatusOf(Set<EvaluatedCondition> conditions) {

+ 8
- 23
server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/ConditionEvaluatorTest.java View File

@@ -34,7 +34,6 @@ import static org.sonar.api.measures.Metric.ValueType.BOOL;
import static org.sonar.api.measures.Metric.ValueType.DATA;
import static org.sonar.api.measures.Metric.ValueType.DISTRIB;
import static org.sonar.api.measures.Metric.ValueType.STRING;
import static org.sonar.server.qualitygate.FakeMeasure.newMeasureOnLeak;

@RunWith(DataProviderRunner.class)
public class ConditionEvaluatorTest {
@@ -59,9 +58,9 @@ public class ConditionEvaluatorTest {
test(new FakeMeasure(10), Condition.Operator.GREATER_THAN, "10", EvaluatedCondition.EvaluationStatus.OK, "10");
test(new FakeMeasure(10), Condition.Operator.GREATER_THAN, "11", EvaluatedCondition.EvaluationStatus.OK, "10");

testOnLeak(newMeasureOnLeak(10), Condition.Operator.GREATER_THAN, "9", EvaluatedCondition.EvaluationStatus.ERROR, "10");
testOnLeak(newMeasureOnLeak(10), Condition.Operator.GREATER_THAN, "10", EvaluatedCondition.EvaluationStatus.OK, "10");
testOnLeak(newMeasureOnLeak(10), Condition.Operator.GREATER_THAN, "11", EvaluatedCondition.EvaluationStatus.OK, "10");
test(new FakeMeasure(10), Condition.Operator.GREATER_THAN, "9", EvaluatedCondition.EvaluationStatus.ERROR, "10");
test(new FakeMeasure(10), Condition.Operator.GREATER_THAN, "10", EvaluatedCondition.EvaluationStatus.OK, "10");
test(new FakeMeasure(10), Condition.Operator.GREATER_THAN, "11", EvaluatedCondition.EvaluationStatus.OK, "10");
}

@Test
@@ -70,9 +69,9 @@ public class ConditionEvaluatorTest {
test(new FakeMeasure(10), Condition.Operator.LESS_THAN, "10", EvaluatedCondition.EvaluationStatus.OK, "10");
test(new FakeMeasure(10), Condition.Operator.LESS_THAN, "11", EvaluatedCondition.EvaluationStatus.ERROR, "10");

testOnLeak(newMeasureOnLeak(10), Condition.Operator.LESS_THAN, "9", EvaluatedCondition.EvaluationStatus.OK, "10");
testOnLeak(newMeasureOnLeak(10), Condition.Operator.LESS_THAN, "10", EvaluatedCondition.EvaluationStatus.OK, "10");
testOnLeak(newMeasureOnLeak(10), Condition.Operator.LESS_THAN, "11", EvaluatedCondition.EvaluationStatus.ERROR, "10");
test(new FakeMeasure(10), Condition.Operator.LESS_THAN, "9", EvaluatedCondition.EvaluationStatus.OK, "10");
test(new FakeMeasure(10), Condition.Operator.LESS_THAN, "10", EvaluatedCondition.EvaluationStatus.OK, "10");
test(new FakeMeasure(10), Condition.Operator.LESS_THAN, "11", EvaluatedCondition.EvaluationStatus.ERROR, "10");
}

@Test
@@ -88,7 +87,6 @@ public class ConditionEvaluatorTest {
test(null, Condition.Operator.LESS_THAN, "9", EvaluatedCondition.EvaluationStatus.OK, null);
}


@Test
@UseDataProvider("unsupportedMetricTypes")
public void fail_when_condition_is_on_unsupported_metric(Metric.ValueType metricType) {
@@ -107,22 +105,9 @@ public class ConditionEvaluatorTest {
};
}

private void test(@Nullable QualityGateEvaluator.Measure measure, Condition.Operator operator, String errorThreshold, EvaluatedCondition.EvaluationStatus expectedStatus, @Nullable String expectedValue) {
Condition condition = new Condition("foo", operator, errorThreshold);

EvaluatedCondition result = ConditionEvaluator.evaluate(condition, new FakeMeasures(measure));

assertThat(result.getStatus()).isEqualTo(expectedStatus);
if (expectedValue == null) {
assertThat(result.getValue()).isNotPresent();
} else {
assertThat(result.getValue()).hasValue(expectedValue);
}
}

private void testOnLeak(QualityGateEvaluator.Measure measure, Condition.Operator operator, String errorThreshold, EvaluatedCondition.EvaluationStatus expectedStatus,
private void test(@Nullable QualityGateEvaluator.Measure measure, Condition.Operator operator, String errorThreshold, EvaluatedCondition.EvaluationStatus expectedStatus,
@Nullable String expectedValue) {
Condition condition = new Condition("new_foo", operator, errorThreshold);
Condition condition = new Condition("foo", operator, errorThreshold);

EvaluatedCondition result = ConditionEvaluator.evaluate(condition, new FakeMeasures(measure));


+ 0
- 13
server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/FakeMeasure.java View File

@@ -25,7 +25,6 @@ import javax.annotation.Nullable;
import org.sonar.api.measures.Metric;

public class FakeMeasure implements QualityGateEvaluator.Measure {
private Double leakValue;
private Double value;
private Metric.ValueType valueType;

@@ -47,13 +46,6 @@ public class FakeMeasure implements QualityGateEvaluator.Measure {
this.valueType = Metric.ValueType.INT;
}

public static FakeMeasure newMeasureOnLeak(@Nullable Integer value) {
FakeMeasure measure = new FakeMeasure();
measure.leakValue = value == null ? null : value.doubleValue();
measure.valueType = Metric.ValueType.INT;
return measure;
}

@Override
public Metric.ValueType getType() {
return valueType;
@@ -68,9 +60,4 @@ public class FakeMeasure implements QualityGateEvaluator.Measure {
public Optional<String> getStringValue() {
return Optional.empty();
}

@Override
public OptionalDouble getNewMetricValue() {
return leakValue == null ? OptionalDouble.empty() : OptionalDouble.of(leakValue);
}
}

+ 5
- 6
server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/QualityGateEvaluatorImplTest.java View File

@@ -39,7 +39,6 @@ import static org.mockito.Mockito.when;
import static org.sonar.api.measures.CoreMetrics.NEW_DUPLICATED_LINES_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_LINES_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_MAINTAINABILITY_RATING_KEY;
import static org.sonar.server.qualitygate.FakeMeasure.newMeasureOnLeak;

public class QualityGateEvaluatorImplTest {
private final MapSettings settings = new MapSettings();
@@ -97,7 +96,7 @@ public class QualityGateEvaluatorImplTest {

QualityGate gate = mock(QualityGate.class);
when(gate.getConditions()).thenReturn(singleton(condition));
QualityGateEvaluator.Measures measures = key -> Optional.of(newMeasureOnLeak(1));
QualityGateEvaluator.Measures measures = key -> Optional.of(new FakeMeasure(1));

assertThat(underTest.evaluate(gate, measures, configuration).getStatus()).isEqualTo(Metric.Level.ERROR);
}
@@ -107,12 +106,12 @@ public class QualityGateEvaluatorImplTest {
Condition condition = new Condition(NEW_DUPLICATED_LINES_KEY, Condition.Operator.GREATER_THAN, "0");

Map<String, QualityGateEvaluator.Measure> notSmallChange = new HashMap<>();
notSmallChange.put(NEW_DUPLICATED_LINES_KEY, newMeasureOnLeak(1));
notSmallChange.put(NEW_LINES_KEY, newMeasureOnLeak(1000));
notSmallChange.put(NEW_DUPLICATED_LINES_KEY, new FakeMeasure(1));
notSmallChange.put(NEW_LINES_KEY, new FakeMeasure(1000));

Map<String, QualityGateEvaluator.Measure> smallChange = new HashMap<>();
smallChange.put(NEW_DUPLICATED_LINES_KEY, newMeasureOnLeak(1));
smallChange.put(NEW_LINES_KEY, newMeasureOnLeak(10));
smallChange.put(NEW_DUPLICATED_LINES_KEY, new FakeMeasure(1));
smallChange.put(NEW_LINES_KEY, new FakeMeasure(10));

QualityGate gate = mock(QualityGate.class);
when(gate.getConditions()).thenReturn(singleton(condition));

+ 10
- 39
server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/LiveMeasureTreeUpdaterImpl.java View File

@@ -158,7 +158,7 @@ public class LiveMeasureTreeUpdaterImpl implements LiveMeasureTreeUpdater {
*/
@Override
public long getChildrenHotspotsReviewed() {
return getChildrenHotspotsReviewed(LiveMeasureDto::getValue, SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY, SECURITY_HOTSPOTS_REVIEWED_KEY, SECURITY_HOTSPOTS_KEY);
return getChildrenHotspotsReviewed(SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY, SECURITY_HOTSPOTS_REVIEWED_KEY, SECURITY_HOTSPOTS_KEY);
}

/**
@@ -175,7 +175,7 @@ public class LiveMeasureTreeUpdaterImpl implements LiveMeasureTreeUpdater {

@Override
public long getChildrenNewHotspotsReviewed() {
return getChildrenHotspotsReviewed(LiveMeasureDto::getVariation, NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY, NEW_SECURITY_HOTSPOTS_REVIEWED_KEY, NEW_SECURITY_HOTSPOTS_KEY);
return getChildrenHotspotsReviewed(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY, NEW_SECURITY_HOTSPOTS_REVIEWED_KEY, NEW_SECURITY_HOTSPOTS_KEY);
}

/**
@@ -186,39 +186,32 @@ public class LiveMeasureTreeUpdaterImpl implements LiveMeasureTreeUpdater {
return componentIndex.getChildren(currentComponent)
.stream()
.map(c -> matrix.getMeasure(c, NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY).or(() -> matrix.getMeasure(c, NEW_SECURITY_HOTSPOTS_KEY)))
.mapToLong(lmOpt -> lmOpt.flatMap(lm -> Optional.ofNullable(lm.getVariation())).orElse(0D).longValue())
.mapToLong(lmOpt -> lmOpt.flatMap(lm -> Optional.ofNullable(lm.getValue())).orElse(0D).longValue())
.sum();
}

private long getChildrenHotspotsReviewed(Function<LiveMeasureDto, Double> valueFunc, String metricKey, String percMetricKey, String hotspotsMetricKey) {
private long getChildrenHotspotsReviewed(String metricKey, String percMetricKey, String hotspotsMetricKey) {
return componentIndex.getChildren(currentComponent)
.stream()
.mapToLong(c -> getHotspotsReviewed(c, valueFunc, metricKey, percMetricKey, hotspotsMetricKey))
.mapToLong(c -> getHotspotsReviewed(c, metricKey, percMetricKey, hotspotsMetricKey))
.sum();
}

private long getHotspotsReviewed(ComponentDto c, Function<LiveMeasureDto, Double> valueFunc, String metricKey, String percMetricKey, String hotspotsMetricKey) {
private long getHotspotsReviewed(ComponentDto c, String metricKey, String percMetricKey, String hotspotsMetricKey) {
Optional<LiveMeasureDto> measure = matrix.getMeasure(c, metricKey);
return measure.map(lm -> Optional.ofNullable(valueFunc.apply(lm)).orElse(0D).longValue())
return measure.map(lm -> Optional.ofNullable(lm.getValue()).orElse(0D).longValue())
.orElseGet(() -> matrix.getMeasure(c, percMetricKey)
.flatMap(percentage -> matrix.getMeasure(c, hotspotsMetricKey)
.map(hotspots -> {
double perc = Optional.ofNullable(valueFunc.apply(percentage)).orElse(0D) / 100D;
double toReview = Optional.ofNullable(valueFunc.apply(hotspots)).orElse(0D);
double perc = Optional.ofNullable(percentage.getValue()).orElse(0D) / 100D;
double toReview = Optional.ofNullable(hotspots.getValue()).orElse(0D);
double reviewed = (toReview * perc) / (1D - perc);
return Math.round(reviewed);
}))
.orElse(0L));
}

public List<Double> getChildrenLeakValues() {
List<ComponentDto> children = componentIndex.getChildren(currentComponent);
return children.stream()
.flatMap(c -> matrix.getMeasure(c, currentFormula.getMetric().getKey()).stream())
.map(LiveMeasureDto::getVariation)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}


@Override
public ComponentDto getComponent() {
@@ -242,38 +235,16 @@ public class LiveMeasureTreeUpdaterImpl implements LiveMeasureTreeUpdater {
return measure.map(LiveMeasureDto::getTextValue);
}

@Override
public Optional<Double> getLeakValue(Metric metric) {
Optional<LiveMeasureDto> measure = matrix.getMeasure(currentComponent, metric.getKey());
return measure.map(LiveMeasureDto::getVariation);
}

@Override
public void setValue(double value) {
String metricKey = currentFormula.getMetric().getKey();
checkState(!currentFormula.isOnLeak(), "Formula of metric %s accepts only leak values", metricKey);
matrix.setValue(currentComponent, metricKey, value);
}

@Override
public void setLeakValue(double value) {
String metricKey = currentFormula.getMetric().getKey();
checkState(currentFormula.isOnLeak(), "Formula of metric %s does not accept leak values", metricKey);
matrix.setLeakValue(currentComponent, metricKey, value);
}

@Override
public void setValue(Rating value) {
String metricKey = currentFormula.getMetric().getKey();
checkState(!currentFormula.isOnLeak(), "Formula of metric %s accepts only leak values", metricKey);
matrix.setValue(currentComponent, metricKey, value);
}

@Override
public void setLeakValue(Rating value) {
String metricKey = currentFormula.getMetric().getKey();
checkState(currentFormula.isOnLeak(), "Formula of metric %s does not accept leak values", metricKey);
matrix.setLeakValue(currentComponent, metricKey, value);
}
}
}

+ 0
- 8
server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/LiveQualityGateComputerImpl.java View File

@@ -135,13 +135,5 @@ public class LiveQualityGateComputerImpl implements LiveQualityGateComputer {
public Optional<String> getStringValue() {
return Optional.ofNullable(dto.getTextValue());
}

@Override
public OptionalDouble getNewMetricValue() {
if (dto.getVariation() == null) {
return OptionalDouble.empty();
}
return OptionalDouble.of(dto.getVariation());
}
}
}

+ 1
- 12
server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/MeasureMatrix.java View File

@@ -102,14 +102,6 @@ class MeasureMatrix {
changeCell(component, metricKey, m -> m.setData(data));
}

void setLeakValue(ComponentDto component, String metricKey, double variation) {
changeCell(component, metricKey, c -> c.setVariation(scale(metricsByKeys.get(metricKey), variation)));
}

void setLeakValue(ComponentDto component, String metricKey, Rating variation) {
setLeakValue(component, metricKey, variation.getIndex());
}

Stream<LiveMeasureDto> getChanged() {
return table.values().stream()
.filter(Objects::nonNull)
@@ -144,7 +136,6 @@ class MeasureMatrix {

private static class MeasureCell {
private final LiveMeasureDto measure;
private final Double initialVariation;
private final Double initialValue;
private final byte[] initialData;
private final String initialTextValue;
@@ -152,7 +143,6 @@ class MeasureMatrix {
private MeasureCell(LiveMeasureDto measure) {
this.measure = measure;
this.initialValue = measure.getValue();
this.initialVariation = measure.getVariation();
this.initialData = measure.getData();
this.initialTextValue = measure.getTextValue();
}
@@ -162,8 +152,7 @@ class MeasureMatrix {
}

public boolean isChanged() {
return !Objects.equals(initialValue, measure.getValue()) || !Objects.equals(initialVariation, measure.getVariation())
|| !Arrays.equals(initialData, measure.getData()) || !Objects.equals(initialTextValue, measure.getTextValue());
return !Objects.equals(initialValue, measure.getValue()) || !Arrays.equals(initialData, measure.getData()) || !Objects.equals(initialTextValue, measure.getTextValue());
}
}
}

+ 0
- 8
server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/MeasureUpdateFormula.java View File

@@ -88,8 +88,6 @@ class MeasureUpdateFormula {

long getChildrenNewHotspotsToReview();

List<Double> getChildrenLeakValues();

ComponentDto getComponent();

DebtRatingGrid getDebtRatingGrid();
@@ -104,14 +102,8 @@ class MeasureUpdateFormula {

Optional<String> getText(Metric metrc);

Optional<Double> getLeakValue(Metric metric);

void setValue(double value);

void setValue(Rating value);

void setLeakValue(double value);

void setLeakValue(Rating value);
}
}

+ 37
- 52
server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/MeasureUpdateFormulaFactoryImpl.java View File

@@ -145,89 +145,89 @@ public class MeasureUpdateFormulaFactoryImpl implements MeasureUpdateFormulaFact
}),

new MeasureUpdateFormula(CoreMetrics.NEW_CODE_SMELLS, true, new AddChildren(),
(context, issues) -> context.setLeakValue(issues.countUnresolvedByType(RuleType.CODE_SMELL, true))),
(context, issues) -> context.setValue(issues.countUnresolvedByType(RuleType.CODE_SMELL, true))),

new MeasureUpdateFormula(CoreMetrics.NEW_BUGS, true, new AddChildren(),
(context, issues) -> context.setLeakValue(issues.countUnresolvedByType(RuleType.BUG, true))),
(context, issues) -> context.setValue(issues.countUnresolvedByType(RuleType.BUG, true))),

new MeasureUpdateFormula(CoreMetrics.NEW_VULNERABILITIES, true, new AddChildren(),
(context, issues) -> context.setLeakValue(issues.countUnresolvedByType(RuleType.VULNERABILITY, true))),
(context, issues) -> context.setValue(issues.countUnresolvedByType(RuleType.VULNERABILITY, true))),

new MeasureUpdateFormula(CoreMetrics.NEW_SECURITY_HOTSPOTS, true, new AddChildren(),
(context, issues) -> context.setLeakValue(issues.countUnresolvedByType(RuleType.SECURITY_HOTSPOT, true))),
(context, issues) -> context.setValue(issues.countUnresolvedByType(RuleType.SECURITY_HOTSPOT, true))),

new MeasureUpdateFormula(CoreMetrics.NEW_VIOLATIONS, true, new AddChildren(),
(context, issues) -> context.setLeakValue(issues.countUnresolved(true))),
(context, issues) -> context.setValue(issues.countUnresolved(true))),

new MeasureUpdateFormula(CoreMetrics.NEW_BLOCKER_VIOLATIONS, true, new AddChildren(),
(context, issues) -> context.setLeakValue(issues.countUnresolvedBySeverity(Severity.BLOCKER, true))),
(context, issues) -> context.setValue(issues.countUnresolvedBySeverity(Severity.BLOCKER, true))),

new MeasureUpdateFormula(CoreMetrics.NEW_CRITICAL_VIOLATIONS, true, new AddChildren(),
(context, issues) -> context.setLeakValue(issues.countUnresolvedBySeverity(Severity.CRITICAL, true))),
(context, issues) -> context.setValue(issues.countUnresolvedBySeverity(Severity.CRITICAL, true))),

new MeasureUpdateFormula(CoreMetrics.NEW_MAJOR_VIOLATIONS, true, new AddChildren(),
(context, issues) -> context.setLeakValue(issues.countUnresolvedBySeverity(Severity.MAJOR, true))),
(context, issues) -> context.setValue(issues.countUnresolvedBySeverity(Severity.MAJOR, true))),

new MeasureUpdateFormula(CoreMetrics.NEW_MINOR_VIOLATIONS, true, new AddChildren(),
(context, issues) -> context.setLeakValue(issues.countUnresolvedBySeverity(Severity.MINOR, true))),
(context, issues) -> context.setValue(issues.countUnresolvedBySeverity(Severity.MINOR, true))),

new MeasureUpdateFormula(CoreMetrics.NEW_INFO_VIOLATIONS, true, new AddChildren(),
(context, issues) -> context.setLeakValue(issues.countUnresolvedBySeverity(Severity.INFO, true))),
(context, issues) -> context.setValue(issues.countUnresolvedBySeverity(Severity.INFO, true))),

new MeasureUpdateFormula(CoreMetrics.NEW_TECHNICAL_DEBT, true, new AddChildren(),
(context, issues) -> context.setLeakValue(issues.sumEffortOfUnresolved(RuleType.CODE_SMELL, true))),
(context, issues) -> context.setValue(issues.sumEffortOfUnresolved(RuleType.CODE_SMELL, true))),

new MeasureUpdateFormula(CoreMetrics.NEW_RELIABILITY_REMEDIATION_EFFORT, true, new AddChildren(),
(context, issues) -> context.setLeakValue(issues.sumEffortOfUnresolved(RuleType.BUG, true))),
(context, issues) -> context.setValue(issues.sumEffortOfUnresolved(RuleType.BUG, true))),

new MeasureUpdateFormula(CoreMetrics.NEW_SECURITY_REMEDIATION_EFFORT, true, new AddChildren(),
(context, issues) -> context.setLeakValue(issues.sumEffortOfUnresolved(RuleType.VULNERABILITY, true))),
(context, issues) -> context.setValue(issues.sumEffortOfUnresolved(RuleType.VULNERABILITY, true))),

new MeasureUpdateFormula(CoreMetrics.NEW_RELIABILITY_RATING, true, new MaxRatingChildren(),
(context, issues) -> {
String highestSeverity = issues.getHighestSeverityOfUnresolved(RuleType.BUG, true).orElse(Severity.INFO);
context.setLeakValue(RATING_BY_SEVERITY.get(highestSeverity));
context.setValue(RATING_BY_SEVERITY.get(highestSeverity));
}),

new MeasureUpdateFormula(CoreMetrics.NEW_SECURITY_RATING, true, new MaxRatingChildren(),
(context, issues) -> {
String highestSeverity = issues.getHighestSeverityOfUnresolved(RuleType.VULNERABILITY, true).orElse(Severity.INFO);
context.setLeakValue(RATING_BY_SEVERITY.get(highestSeverity));
context.setValue(RATING_BY_SEVERITY.get(highestSeverity));
}),

new MeasureUpdateFormula(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, true,
(context, formula) -> context.setLeakValue(context.getLeakValue(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS).orElse(0D) + context.getChildrenNewHotspotsReviewed()),
(context, issues) -> context.setLeakValue(issues.countHotspotsByStatus(Issue.STATUS_REVIEWED, true))),
(context, formula) -> context.setValue(context.getValue(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS).orElse(0D) + context.getChildrenNewHotspotsReviewed()),
(context, issues) -> context.setValue(issues.countHotspotsByStatus(Issue.STATUS_REVIEWED, true))),

new MeasureUpdateFormula(NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, true,
(context, formula) -> context.setLeakValue(context.getLeakValue(NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS).orElse(0D) + context.getChildrenNewHotspotsToReview()),
(context, issues) -> context.setLeakValue(issues.countHotspotsByStatus(Issue.STATUS_TO_REVIEW, true))),
(context, formula) -> context.setValue(context.getValue(NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS).orElse(0D) + context.getChildrenNewHotspotsToReview()),
(context, issues) -> context.setValue(issues.countHotspotsByStatus(Issue.STATUS_TO_REVIEW, true))),

new MeasureUpdateFormula(NEW_SECURITY_HOTSPOTS_REVIEWED, true,
(context, formula) -> {
Optional<Double> percent = computePercent(
context.getLeakValue(NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS).orElse(0D).longValue(),
context.getLeakValue(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS).orElse(0D).longValue());
percent.ifPresent(context::setLeakValue);
context.getValue(NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS).orElse(0D).longValue(),
context.getValue(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS).orElse(0D).longValue());
percent.ifPresent(context::setValue);
},
(context, issues) -> computePercent(issues.countHotspotsByStatus(Issue.STATUS_TO_REVIEW, true), issues.countHotspotsByStatus(Issue.STATUS_REVIEWED, true))
.ifPresent(context::setLeakValue)),
.ifPresent(context::setValue)),

new MeasureUpdateFormula(CoreMetrics.NEW_SECURITY_REVIEW_RATING, true,
(context, formula) -> context.setLeakValue(computeRating(context.getLeakValue(NEW_SECURITY_HOTSPOTS_REVIEWED).orElse(null))),
(context, formula) -> context.setValue(computeRating(context.getValue(NEW_SECURITY_HOTSPOTS_REVIEWED).orElse(null))),
(context, issues) -> {
Optional<Double> percent = computePercent(issues.countHotspotsByStatus(Issue.STATUS_TO_REVIEW, true), issues.countHotspotsByStatus(Issue.STATUS_REVIEWED, true));
context.setLeakValue(computeRating(percent.orElse(null)));
context.setValue(computeRating(percent.orElse(null)));
}),

new MeasureUpdateFormula(CoreMetrics.NEW_SQALE_DEBT_RATIO, true,
(context, formula) -> context.setLeakValue(100.0D * newDebtDensity(context)),
(context, issues) -> context.setLeakValue(100.0D * newDebtDensity(context)),
(context, formula) -> context.setValue(100.0D * newDebtDensity(context)),
(context, issues) -> context.setValue(100.0D * newDebtDensity(context)),
asList(CoreMetrics.NEW_TECHNICAL_DEBT, CoreMetrics.NEW_DEVELOPMENT_COST)),

new MeasureUpdateFormula(CoreMetrics.NEW_MAINTAINABILITY_RATING, true,
(context, formula) -> context.setLeakValue(context.getDebtRatingGrid().getRatingForDensity(newDebtDensity(context))),
(context, issues) -> context.setLeakValue(context.getDebtRatingGrid().getRatingForDensity(newDebtDensity(context))),
(context, formula) -> context.setValue(context.getDebtRatingGrid().getRatingForDensity(newDebtDensity(context))),
(context, issues) -> context.setValue(context.getDebtRatingGrid().getRatingForDensity(newDebtDensity(context))),
asList(CoreMetrics.NEW_TECHNICAL_DEBT, CoreMetrics.NEW_DEVELOPMENT_COST)));

private static final Set<Metric> FORMULA_METRICS = MeasureUpdateFormulaFactory.extractMetrics(FORMULAS);
@@ -242,8 +242,8 @@ public class MeasureUpdateFormulaFactoryImpl implements MeasureUpdateFormulaFact
}

private static double newDebtDensity(MeasureUpdateFormula.Context context) {
double debt = Math.max(context.getLeakValue(CoreMetrics.NEW_TECHNICAL_DEBT).orElse(0.0D), 0.0D);
Optional<Double> devCost = context.getLeakValue(CoreMetrics.NEW_DEVELOPMENT_COST);
double debt = Math.max(context.getValue(CoreMetrics.NEW_TECHNICAL_DEBT).orElse(0.0D), 0.0D);
Optional<Double> devCost = context.getValue(CoreMetrics.NEW_DEVELOPMENT_COST);
if (devCost.isPresent() && Double.doubleToRawLongBits(devCost.get()) > 0L) {
return debt / devCost.get();
}
@@ -260,33 +260,18 @@ public class MeasureUpdateFormulaFactoryImpl implements MeasureUpdateFormulaFact
static class AddChildren implements BiConsumer<MeasureUpdateFormula.Context, MeasureUpdateFormula> {
@Override
public void accept(MeasureUpdateFormula.Context context, MeasureUpdateFormula formula) {
double sum;
if (formula.isOnLeak()) {
sum = context.getChildrenLeakValues().stream().mapToDouble(x -> x).sum();
context.setLeakValue(context.getLeakValue(formula.getMetric()).orElse(0D) + sum);
} else {
sum = context.getChildrenValues().stream().mapToDouble(x -> x).sum();
context.setValue(context.getValue(formula.getMetric()).orElse(0D) + sum);
}
double sum = context.getChildrenValues().stream().mapToDouble(x -> x).sum();
context.setValue(context.getValue(formula.getMetric()).orElse(0D) + sum);
}
}

private static class MaxRatingChildren implements BiConsumer<MeasureUpdateFormula.Context, MeasureUpdateFormula> {
@Override
public void accept(MeasureUpdateFormula.Context context, MeasureUpdateFormula formula) {
OptionalInt max;
if (formula.isOnLeak()) {
max = context.getChildrenLeakValues().stream().mapToInt(Double::intValue).max();
if (max.isPresent()) {
int currentRating = context.getLeakValue(formula.getMetric()).map(Double::intValue).orElse(Rating.A.getIndex());
context.setLeakValue(Rating.valueOf(Math.max(currentRating, max.getAsInt())));
}
} else {
max = context.getChildrenValues().stream().mapToInt(Double::intValue).max();
if (max.isPresent()) {
int currentRating = context.getValue(formula.getMetric()).map(Double::intValue).orElse(Rating.A.getIndex());
context.setValue(Rating.valueOf(Math.max(currentRating, max.getAsInt())));
}
OptionalInt max = context.getChildrenValues().stream().mapToInt(Double::intValue).max();
if (max.isPresent()) {
int currentRating = context.getValue(formula.getMetric()).map(Double::intValue).orElse(Rating.A.getIndex());
context.setValue(Rating.valueOf(Math.max(currentRating, max.getAsInt())));
}
}
}

+ 3
- 2
server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java View File

@@ -394,7 +394,8 @@ public class ComponentTreeAction implements MeasuresWsAction {
Measures.Measure.Builder measureBuilder = Measures.Measure.newBuilder();
for (Map.Entry<MetricDto, ComponentTreeData.Measure> entry : measures.entrySet()) {
ComponentTreeData.Measure measure = entry.getValue();
updateMeasureBuilder(measureBuilder, entry.getKey(), measure.getValue(), measure.getData(), measure.getVariation());
boolean onNewCode = entry.getKey().getKey().startsWith("new_");
updateMeasureBuilder(measureBuilder, entry.getKey(), measure.getValue(), measure.getData(), onNewCode);
wsComponent.addMeasures(measureBuilder);
measureBuilder.clear();
}
@@ -588,7 +589,7 @@ public class ComponentTreeAction implements MeasuresWsAction {

return components
.stream()
.filter(new HasMeasure(measuresByComponentUuidAndMetric, metricToSort.get(), wsRequest.getMetricPeriodSort()))
.filter(new HasMeasure(measuresByComponentUuidAndMetric, metricToSort.get()))
.collect(MoreCollectors.toList(components.size()));
}


+ 2
- 12
server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java View File

@@ -157,16 +157,14 @@ class ComponentTreeData {
static class Measure {
private double value;
private String data;
private double variation;

public Measure(@Nullable String data, @Nullable Double value, @Nullable Double variation) {
public Measure(@Nullable String data, @Nullable Double value) {
this.data = data;
this.value = toPrimitive(value);
this.variation = toPrimitive(variation);
}

private Measure(LiveMeasureDto measureDto) {
this(measureDto.getDataAsString(), measureDto.getValue(), measureDto.getVariation());
this(measureDto.getDataAsString(), measureDto.getValue());
}

public double getValue() {
@@ -182,14 +180,6 @@ class ComponentTreeData {
return data;
}

public double getVariation() {
return variation;
}

public boolean isVariationSet() {
return !isNaN(variation);
}

static Measure createFromMeasureDto(LiveMeasureDto measureDto) {
return new Measure(measureDto);
}

+ 2
- 2
server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeSort.java View File

@@ -237,10 +237,10 @@ public class ComponentTreeSort {
@Override
public Double apply(@Nonnull ComponentDto input) {
ComponentTreeData.Measure measure = measuresByComponentUuidAndMetric.get(input.uuid(), metric);
if (measure == null || !measure.isVariationSet()) {
if (measure == null || !metric.getKey().startsWith("new_")) {
return null;
}
return measure.getVariation();
return measure.getValue();
}
}


+ 4
- 24
server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/HasMeasure.java View File

@@ -22,7 +22,6 @@ package org.sonar.server.measure.ws;
import com.google.common.collect.Table;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.metric.MetricDto;

@@ -31,10 +30,8 @@ import static org.sonar.server.measure.ws.ComponentTreeData.Measure;
class HasMeasure implements Predicate<ComponentDto> {
private final Predicate<ComponentDto> predicate;

HasMeasure(Table<String, MetricDto, ComponentTreeData.Measure> table, MetricDto metric, @Nullable Integer metricPeriodSort) {
this.predicate = metricPeriodSort == null
? new HasAbsoluteValue(table, metric)
: new HasValueOnPeriod(table, metric);
HasMeasure(Table<String, MetricDto, ComponentTreeData.Measure> table, MetricDto metric) {
this.predicate = new HasValue(table, metric);
}

@Override
@@ -42,11 +39,11 @@ class HasMeasure implements Predicate<ComponentDto> {
return predicate.test(input);
}

private static class HasAbsoluteValue implements Predicate<ComponentDto> {
private static class HasValue implements Predicate<ComponentDto> {
private final Table<String, MetricDto, ComponentTreeData.Measure> table;
private final MetricDto metric;

private HasAbsoluteValue(Table<String, MetricDto, ComponentTreeData.Measure> table, MetricDto metric) {
private HasValue(Table<String, MetricDto, ComponentTreeData.Measure> table, MetricDto metric) {
this.table = table;
this.metric = metric;
}
@@ -57,21 +54,4 @@ class HasMeasure implements Predicate<ComponentDto> {
return measure != null && (measure.isValueSet() || measure.getData() != null);
}
}

private static class HasValueOnPeriod implements Predicate<ComponentDto> {
private final Table<String, MetricDto, ComponentTreeData.Measure> table;
private final MetricDto metric;

private HasValueOnPeriod(Table<String, MetricDto, ComponentTreeData.Measure> table, MetricDto metric) {
this.table = table;
this.metric = metric;
}

@Override
public boolean test(@Nonnull ComponentDto input) {
Measure measure = table.get(input.uuid(), metric);
return measure != null && measure.isVariationSet();
}
}

}

+ 23
- 23
server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java View File

@@ -29,7 +29,6 @@ import org.sonarqube.ws.Measures.Measure;
import static java.lang.Double.compare;
import static java.util.Optional.ofNullable;
import static org.sonar.server.measure.ws.MeasureValueFormatter.formatMeasureValue;
import static org.sonar.server.measure.ws.MeasureValueFormatter.formatNumericalValue;

class MeasureDtoToWsMeasure {

@@ -38,37 +37,38 @@ class MeasureDtoToWsMeasure {
}

static void updateMeasureBuilder(Measure.Builder measureBuilder, MetricDto metricDto, MeasureDto measureDto) {
Double value = measureDto.getValue();
Double variation = measureDto.getVariation();
updateMeasureBuilder(measureBuilder, metricDto, value == null ? Double.NaN : value, measureDto.getData(), variation == null ? Double.NaN : variation);
double value = measureDto.getValue() == null ? Double.NaN : measureDto.getValue();
boolean onNewCode = metricDto.getKey().startsWith("new_");
updateMeasureBuilder(measureBuilder, metricDto, value, measureDto.getData(), onNewCode);
}

static void updateMeasureBuilder(Measure.Builder measureBuilder, MetricDto metricDto, LiveMeasureDto measureDto) {
Double value = measureDto.getValue();
Double variation = measureDto.getVariation();
updateMeasureBuilder(measureBuilder, metricDto, value == null ? Double.NaN : value, measureDto.getDataAsString(), variation == null ? Double.NaN : variation);
double value = measureDto.getValue() == null ? Double.NaN : measureDto.getValue();
boolean onNewCode = metricDto.getKey().startsWith("new_");
updateMeasureBuilder(measureBuilder, metricDto, value, measureDto.getDataAsString(), onNewCode);
}

static void updateMeasureBuilder(Measure.Builder measureBuilder, MetricDto metric, double doubleValue, @Nullable String stringValue, double variation) {
static void updateMeasureBuilder(Measure.Builder measureBuilder, MetricDto metric, double doubleValue, @Nullable String stringValue, boolean onNewCode) {
measureBuilder.setMetric(metric.getKey());
Double bestValue = metric.getBestValue();
// a measure value can be null, new_violations metric for example
if (!Double.isNaN(doubleValue) || stringValue != null) {
measureBuilder.setValue(formatMeasureValue(doubleValue, stringValue, metric));
ofNullable(bestValue).ifPresent(v -> measureBuilder.setBestValue(compare(doubleValue, v) == 0));
}

Measures.PeriodValue.Builder periodBuilder = Measures.PeriodValue.newBuilder();
if (Double.isNaN(variation)) {
if (Double.isNaN(doubleValue) && stringValue == null) {
return;
}
Measures.PeriodValue.Builder builderForValue = periodBuilder
.clear()
.setIndex(1)
.setValue(formatNumericalValue(variation, metric));
ofNullable(bestValue).ifPresent(v -> builderForValue.setBestValue(compare(variation, v) == 0));
//deprecated since 8.1
measureBuilder.getPeriodsBuilder().addPeriodsValue(builderForValue);
measureBuilder.setPeriod(builderForValue);

if (!onNewCode) {
measureBuilder.setValue(formatMeasureValue(doubleValue, stringValue, metric));
ofNullable(bestValue).ifPresent(v -> measureBuilder.setBestValue(compare(doubleValue, v) == 0));
} else {
Measures.PeriodValue.Builder periodBuilder = Measures.PeriodValue.newBuilder();
Measures.PeriodValue.Builder builderForValue = periodBuilder
.clear()
.setIndex(1)
.setValue(formatMeasureValue(doubleValue, stringValue, metric));
ofNullable(bestValue).ifPresent(v -> builderForValue.setBestValue(compare(doubleValue, v) == 0));
//deprecated since 8.1
measureBuilder.getPeriodsBuilder().addPeriodsValue(builderForValue);
measureBuilder.setPeriod(builderForValue);
}
}
}

+ 1
- 9
server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/MetricDtoWithBestValue.java View File

@@ -20,7 +20,6 @@
package org.sonar.server.measure.ws;

import com.google.common.collect.ImmutableSortedSet;
import java.util.Locale;
import java.util.Set;
import java.util.function.Predicate;
import org.sonar.api.resources.Qualifiers;
@@ -29,7 +28,6 @@ import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.metric.MetricDto;

public class MetricDtoWithBestValue {
private static final String LOWER_CASE_NEW_METRIC_PREFIX = "new_";
private static final Set<String> QUALIFIERS_ELIGIBLE_FOR_BEST_VALUE = ImmutableSortedSet.of(Qualifiers.FILE, Qualifiers.UNIT_TEST_FILE);

private final MetricDto metric;
@@ -38,13 +36,7 @@ public class MetricDtoWithBestValue {
MetricDtoWithBestValue(MetricDto metric) {
this.metric = metric;
LiveMeasureDto measure = new LiveMeasureDto().setMetricUuid(metric.getUuid());
boolean isNewTypeMetric = metric.getKey().toLowerCase(Locale.ENGLISH).startsWith(LOWER_CASE_NEW_METRIC_PREFIX);
if (isNewTypeMetric) {
measure.setVariation(metric.getBestValue());
} else {
measure.setValue(metric.getBestValue());
}

measure.setValue(metric.getBestValue());
this.bestValue = measure;
}


+ 4
- 8
server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/PrMeasureFix.java View File

@@ -121,7 +121,7 @@ class PrMeasureFix {
String originalKey = METRICS.inverse().get(metric.getKey());
if (originalKey != null && requestedMetricKeys.contains(originalKey)) {
for (Map.Entry<String, ComponentTreeData.Measure> e : measuresByComponentUuidAndMetric.column(metric).entrySet()) {
newEntries.put(e.getKey(), copyMeasureToVariation(e.getValue()));
newEntries.put(e.getKey(), e.getValue());
}

MetricDto originalMetric = metricByKey.get(originalKey);
@@ -142,7 +142,7 @@ class PrMeasureFix {

if (originalKey != null && requestedMetricKeys.contains(originalKey)) {
MetricDto metricDto = metricByKey.get(originalKey);
newEntries.put(metricDto, copyMeasureToVariation(e.getValue(), metricDto.getUuid()));
newEntries.put(metricDto, copyMeasure(e.getValue(), metricDto.getUuid()));
}
}

@@ -150,13 +150,9 @@ class PrMeasureFix {
measuresByMetric.putAll(newEntries);
}

private static ComponentTreeData.Measure copyMeasureToVariation(ComponentTreeData.Measure measure) {
return new ComponentTreeData.Measure(null, null, measure.getValue());
}

private static LiveMeasureDto copyMeasureToVariation(LiveMeasureDto dto, String metricUuid) {
private static LiveMeasureDto copyMeasure(LiveMeasureDto dto, String metricUuid) {
LiveMeasureDto copy = new LiveMeasureDto();
copy.setVariation(dto.getValue());
copy.setValue(dto.getValue());
copy.setProjectUuid(dto.getProjectUuid());
copy.setComponentUuid(dto.getComponentUuid());
copy.setMetricUuid(metricUuid);

+ 1
- 4
server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/SearchHistoryResponseFactory.java View File

@@ -35,7 +35,6 @@ import org.sonarqube.ws.Measures.SearchHistoryResponse.HistoryValue;

import static org.sonar.api.utils.DateUtils.formatDateTime;
import static org.sonar.server.measure.ws.MeasureValueFormatter.formatMeasureValue;
import static org.sonar.server.measure.ws.MeasureValueFormatter.formatNumericalValue;

class SearchHistoryResponseFactory {
private final SearchHistoryResult result;
@@ -105,9 +104,7 @@ class SearchHistoryResponseFactory {

private SnapshotDto addValue(SnapshotDto analysis, MetricDto dbMetric, @Nullable MeasureDto dbMeasure) {
if (dbMeasure != null) {
String measureValue = dbMetric.getKey().startsWith("new_")
? formatNumericalValue(dbMeasure.getVariation(), dbMetric)
: formatMeasureValue(dbMeasure, dbMetric);
String measureValue = formatMeasureValue(dbMeasure, dbMetric);
if (measureValue != null) {
value.setValue(measureValue);
}

+ 3
- 10
server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/SearchHistoryResult.java View File

@@ -129,17 +129,10 @@ public class SearchHistoryResult {
}

private static MeasureDto toBestValue(MetricDto metric, SnapshotDto analysis) {
MeasureDto measure = new MeasureDto()
return new MeasureDto()
.setMetricUuid(metric.getUuid())
.setAnalysisUuid(analysis.getUuid());

if (metric.getKey().startsWith("new_")) {
measure.setVariation(metric.getBestValue());
} else {
measure.setValue(metric.getBestValue());
}

return measure;
.setAnalysisUuid(analysis.getUuid())
.setValue(metric.getBestValue());
}

Common.Paging getPaging() {

+ 2
- 10
server/sonar-webserver-webapi/src/main/resources/org/sonar/server/measure/ws/component-example.json View File

@@ -8,11 +8,7 @@
"measures": [
{
"metric": "complexity",
"value": "12",
"period": {
"value": "2",
"bestValue": false
}
"value": "12"
},
{
"metric": "new_violations",
@@ -23,11 +19,7 @@
},
{
"metric": "ncloc",
"value": "114",
"period": {
"value": "3",
"bestValue": false
}
"value": "114"
}
]
},

+ 0
- 0
server/sonar-webserver-webapi/src/main/resources/org/sonar/server/measure/ws/component_tree-example.json View File


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save