@@ -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(); | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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); | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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}; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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}; | |||
} | |||
} |
@@ -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))); | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} | |||
} |
@@ -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: |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; |
@@ -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); | |||
} | |||
} | |||
} |
@@ -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) { |
@@ -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); | |||
} | |||
@@ -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()); |
@@ -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(); | |||
} |
@@ -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(); |
@@ -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; | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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(); | |||
} |
@@ -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(); | |||
} | |||
@@ -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()); | |||
} | |||
} | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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<>(); | |||
@@ -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); | |||
} | |||
} |
@@ -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) { |
@@ -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(); | |||
} | |||
@@ -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); |
@@ -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); |
@@ -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 |
@@ -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) { |
@@ -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); | |||
} | |||
} |
@@ -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) { |
@@ -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) { |
@@ -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); | |||
} | |||
} | |||
@@ -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) { |
@@ -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) { |
@@ -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); | |||
} | |||
@@ -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); | |||
} | |||
@@ -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()); |
@@ -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); | |||
@@ -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()) |
@@ -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 |
@@ -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"); |
@@ -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; |
@@ -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('}'); |
@@ -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) |
@@ -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; |
@@ -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> |
@@ -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> |
@@ -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 | |||
); |
@@ -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() { |
@@ -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 |
@@ -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)); |
@@ -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++); | |||
} | |||
} |
@@ -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, |
@@ -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) | |||
; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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"); | |||
} | |||
} |
@@ -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"); | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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++); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); |
@@ -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); |
@@ -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); |
@@ -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); |
@@ -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()); |
@@ -55,7 +55,5 @@ public interface QualityGateEvaluator { | |||
OptionalDouble getValue(); | |||
Optional<String> getStringValue(); | |||
OptionalDouble getNewMetricValue(); | |||
} | |||
} |
@@ -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) { |
@@ -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)); | |||
@@ -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); | |||
} | |||
} |
@@ -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)); |
@@ -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); | |||
} | |||
} | |||
} |
@@ -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()); | |||
} | |||
} | |||
} |
@@ -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()); | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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()))); | |||
} | |||
} | |||
} |
@@ -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())); | |||
} | |||
@@ -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); | |||
} |
@@ -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(); | |||
} | |||
} | |||
@@ -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(); | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
} |
@@ -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; | |||
} | |||
@@ -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); |
@@ -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); | |||
} |
@@ -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() { |
@@ -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" | |||
} | |||
] | |||
}, |