aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-core
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2013-11-19 08:22:23 +0100
committerJulien Lancelot <julien.lancelot@sonarsource.com>2013-11-20 08:12:02 +0100
commitc1bbe9af51af88e0f5c6a78833ef646cb512bd6e (patch)
tree1b112ac559af5ea4cdfa3cd732e09ccedbfcb08d /sonar-core
parent081e080bf8b3e7e16bd6459dcb4e9f43857b6cf1 (diff)
downloadsonarqube-c1bbe9af51af88e0f5c6a78833ef646cb512bd6e.tar.gz
sonarqube-c1bbe9af51af88e0f5c6a78833ef646cb512bd6e.zip
SONAR-4775 The technical debt should be related only to issues
Diffstat (limited to 'sonar-core')
-rw-r--r--sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtCalculator.java111
-rw-r--r--sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtConverter.java15
-rw-r--r--sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtRequirement.java20
-rw-r--r--sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporter.java29
-rw-r--r--sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/AbstractFunction.java51
-rw-r--r--sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/ConstantFunction.java53
-rw-r--r--sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/Function.java37
-rw-r--r--sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/Functions.java57
-rw-r--r--sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearFunction.java57
-rw-r--r--sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearWithOffsetFunction.java48
-rw-r--r--sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearWithThresholdFunction.java49
-rw-r--r--sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/package-info.java23
-rw-r--r--sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtCalculatorTest.java182
-rw-r--r--sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtConverterTest.java7
-rw-r--r--sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtRequirementTest.java89
-rw-r--r--sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest.java86
-rw-r--r--sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/ConstantFunctionTest.java77
-rw-r--r--sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/FunctionsTest.java37
-rw-r--r--sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearFunctionTest.java96
-rw-r--r--sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearWithOffsetFunctionTest.java66
-rw-r--r--sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearWithThresholdFunctionTest.java69
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_badly-formatted.xml6
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_with_deprecated_constant_per_file.xml20
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_with_deprecated_linear_with_threshold.xml32
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_with_linear.xml (renamed from sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML.xml)6
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_with_linear_with_offset.xml30
26 files changed, 294 insertions, 1059 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtCalculator.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtCalculator.java
index fabda2a3b89..d6a6cdc6c93 100644
--- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtCalculator.java
+++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtCalculator.java
@@ -19,132 +19,41 @@
*/
package org.sonar.core.technicaldebt;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Maps;
-import org.slf4j.LoggerFactory;
+import com.google.common.base.Objects;
import org.sonar.api.BatchExtension;
-import org.sonar.api.batch.DecoratorContext;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.internal.WorkDayDuration;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.MeasuresFilters;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.rules.Violation;
-import org.sonar.core.technicaldebt.functions.Functions;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
/**
* Computes the remediation cost based on the quality and analysis models.
*/
public class TechnicalDebtCalculator implements BatchExtension {
- private double total = 0.0;
- private Map<TechnicalDebtCharacteristic, Double> characteristicCosts = Maps.newHashMap();
- private Map<TechnicalDebtRequirement, Double> requirementCosts = Maps.newHashMap();
-
- private Functions functions;
private final TechnicalDebtConverter converter;
private TechnicalDebtModel technicalDebtModel;
- public TechnicalDebtCalculator(TechnicalDebtModel technicalDebtModel, Functions functions, TechnicalDebtConverter converter) {
+ public TechnicalDebtCalculator(TechnicalDebtModel technicalDebtModel, TechnicalDebtConverter converter) {
this.technicalDebtModel = technicalDebtModel;
- this.functions = functions;
this.converter = converter;
}
public WorkDayDuration calculTechnicalDebt(Issue issue) {
TechnicalDebtRequirement requirement = technicalDebtModel.getRequirementByRule(issue.ruleKey().repository(), issue.ruleKey().rule());
if (requirement != null) {
- return converter.fromMinutes(functions.costInMinutes(requirement, issue));
+ return converter.fromMinutes(calculTechnicalDebt(requirement, issue));
}
return null;
}
- public void compute(DecoratorContext context) {
- reset();
-
- // group violations by requirement
- ListMultimap<TechnicalDebtRequirement, Violation> violationsByRequirement = groupViolations(context);
-
- // the total cost is: cost(violations)
- for (TechnicalDebtRequirement requirement : technicalDebtModel.getAllRequirements()) {
- List<Violation> violations = violationsByRequirement.get(requirement);
- double allViolationsCost = computeTechnicalDebt(CoreMetrics.TECHNICAL_DEBT, context, requirement, violations);
- updateRequirementCosts(requirement, allViolationsCost);
- }
- }
-
- public double getTotal() {
- return total;
- }
-
- public Map<TechnicalDebtCharacteristic, Double> getCharacteristicCosts() {
- return characteristicCosts;
- }
-
- public Map<TechnicalDebtRequirement, Double> getRequirementCosts() {
- return requirementCosts;
- }
-
- @VisibleForTesting
- protected ListMultimap<TechnicalDebtRequirement, Violation> groupViolations(DecoratorContext context) {
- ListMultimap<TechnicalDebtRequirement, Violation> violationsByRequirement = ArrayListMultimap.create();
- for (Violation violation : context.getViolations()) {
- String repositoryKey = violation.getRule().getRepositoryKey();
- String key = violation.getRule().getKey();
- TechnicalDebtRequirement requirement = technicalDebtModel.getRequirementByRule(repositoryKey, key);
- if (requirement == null) {
- LoggerFactory.getLogger(getClass()).debug("No technical debt requirement for: " + repositoryKey + "/" + key);
- } else {
- violationsByRequirement.put(requirement, violation);
- }
- }
- return violationsByRequirement;
- }
-
- @VisibleForTesting
- protected void updateRequirementCosts(TechnicalDebtRequirement requirement, double cost) {
- requirementCosts.put(requirement, cost);
- total += cost;
- propagateCostInParents(requirement.getParent(), cost);
- }
-
- private double computeTechnicalDebt(Metric metric, DecoratorContext context, TechnicalDebtRequirement requirement, Collection<Violation> violations) {
- double cost = 0.0;
- if (violations != null) {
- cost = functions.costInHours(requirement, violations);
- }
+ private long calculTechnicalDebt(TechnicalDebtRequirement requirement, Issue issue) {
+ long effortToFix = Objects.firstNonNull(issue.effortToFix(), 1l).longValue();
- for (Measure measure : context.getChildrenMeasures(MeasuresFilters.characteristic(metric, requirement.toCharacteristic()))) {
- if (measure.getCharacteristic() != null && measure.getCharacteristic().equals(requirement.toCharacteristic()) && measure.getValue() != null) {
- cost += measure.getValue();
- }
- }
- return cost;
- }
+ WorkUnit factorUnit = requirement.getRemediationFactor();
+ long factor = factorUnit != null ? converter.toMinutes(factorUnit) : 0l;
- private void reset() {
- total = 0.0;
- characteristicCosts.clear();
- requirementCosts.clear();
- }
+ WorkUnit offsetUnit = requirement.getOffset();
+ long offset = offsetUnit != null ? converter.toMinutes(offsetUnit) : 0l;
- private void propagateCostInParents(TechnicalDebtCharacteristic characteristic, double cost) {
- if (characteristic != null) {
- Double parentCost = characteristicCosts.get(characteristic);
- if (parentCost == null) {
- characteristicCosts.put(characteristic, cost);
- } else {
- characteristicCosts.put(characteristic, cost + parentCost);
- }
- propagateCostInParents(characteristic.getParent(), cost);
- }
+ return effortToFix * factor + offset;
}
-
}
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtConverter.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtConverter.java
index 962483a6887..c2b204a0a2b 100644
--- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtConverter.java
+++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtConverter.java
@@ -35,21 +35,6 @@ public class TechnicalDebtConverter implements BatchComponent, ServerComponent {
this.hoursInDay = settings.getInt(PROPERTY_HOURS_IN_DAY);
}
- public double toDays(WorkUnit factor) {
- if (StringUtils.equals(WorkUnit.DAYS, factor.getUnit())) {
- return factor.getValue();
-
- } else if (StringUtils.equals(WorkUnit.HOURS, factor.getUnit())) {
- return factor.getValue() / hoursInDay;
-
- } else if (StringUtils.equals(WorkUnit.MINUTES, factor.getUnit())) {
- return factor.getValue() / (hoursInDay * 60.0);
-
- } else {
- throw new IllegalArgumentException("Unknown remediation factor unit: " + factor.getUnit());
- }
- }
-
public long toMinutes(WorkUnit factor) {
if (StringUtils.equals(WorkUnit.DAYS, factor.getUnit())) {
return Double.valueOf(factor.getValue() * hoursInDay * 60d).longValue();
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtRequirement.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtRequirement.java
index f597f4bace3..df07400c8d6 100644
--- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtRequirement.java
+++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtRequirement.java
@@ -21,9 +21,8 @@ package org.sonar.core.technicaldebt;
import org.sonar.api.qualitymodel.Characteristic;
import org.sonar.api.rules.Rule;
-import org.sonar.core.technicaldebt.functions.LinearFunction;
-import org.sonar.core.technicaldebt.functions.LinearWithOffsetFunction;
-import org.sonar.core.technicaldebt.functions.LinearWithThresholdFunction;
+
+import javax.annotation.CheckForNull;
public class TechnicalDebtRequirement {
@@ -31,6 +30,10 @@ public class TechnicalDebtRequirement {
public static final String PROPERTY_REMEDIATION_FACTOR = "remediationFactor";
public static final String PROPERTY_OFFSET = "offset";
+ public static final String FUNCTION_LINEAR = "linear";
+ public static final String FUNCTION_LINEAR_WITH_OFFSET = "linear_offset";
+ public static final String FUNCTION_CONSTANT_PER_ISSUE = "constant_issue";
+
private Rule rule;
private TechnicalDebtCharacteristic parent;
private org.sonar.api.qualitymodel.Characteristic characteristic;
@@ -49,16 +52,17 @@ public class TechnicalDebtRequirement {
}
private void initFunction() {
- function = characteristic.getPropertyTextValue(PROPERTY_REMEDIATION_FUNCTION, LinearFunction.FUNCTION_LINEAR);
+ function = characteristic.getPropertyTextValue(PROPERTY_REMEDIATION_FUNCTION, FUNCTION_LINEAR);
}
private void initFactor() {
- factor = WorkUnit.create(characteristic.getPropertyValue(PROPERTY_REMEDIATION_FACTOR, null),
- characteristic.getPropertyTextValue(PROPERTY_REMEDIATION_FACTOR, null));
+ if (FUNCTION_LINEAR.equals(function) || FUNCTION_LINEAR_WITH_OFFSET.equals(function)) {
+ factor = WorkUnit.create(characteristic.getPropertyValue(PROPERTY_REMEDIATION_FACTOR, null), characteristic.getPropertyTextValue(PROPERTY_REMEDIATION_FACTOR, null));
+ }
}
private void initOffset() {
- if (LinearWithOffsetFunction.FUNCTION_LINEAR_WITH_OFFSET.equals(function) || LinearWithThresholdFunction.FUNCTION_LINEAR_WITH_THRESHOLD.equals(function)) {
+ if (FUNCTION_LINEAR_WITH_OFFSET.equals(function) || FUNCTION_CONSTANT_PER_ISSUE.equals(function)) {
offset = WorkUnit.create(characteristic.getPropertyValue(PROPERTY_OFFSET, null),
characteristic.getPropertyTextValue(PROPERTY_OFFSET, null));
}
@@ -76,10 +80,12 @@ public class TechnicalDebtRequirement {
return function;
}
+ @CheckForNull
public WorkUnit getRemediationFactor() {
return factor;
}
+ @CheckForNull
public WorkUnit getOffset() {
return offset;
}
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporter.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporter.java
index 44ea20fbcd7..860956d5f32 100644
--- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporter.java
+++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporter.java
@@ -30,6 +30,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.ServerExtension;
import org.sonar.api.qualitymodel.Characteristic;
+import org.sonar.api.qualitymodel.CharacteristicProperty;
import org.sonar.api.qualitymodel.Model;
import org.sonar.api.rules.Rule;
import org.sonar.api.utils.ValidationMessages;
@@ -124,8 +125,11 @@ public class TechnicalDebtXMLImporter implements ServerExtension {
fillRule(characteristic, ruleRepositoryKey, ruleKey, messages, technicalDebtRuleCache);
if (StringUtils.isNotBlank(characteristic.getKey()) || characteristic.getRule() != null) {
- addCharacteristicToModel(model, characteristic, children);
- return characteristic;
+ Characteristic convertedCharacteristic = processDeprecatedFunctionsOnRequirement(characteristic, messages);
+ if (convertedCharacteristic != null) {
+ addCharacteristicToModel(model, characteristic, children);
+ return characteristic;
+ }
}
return null;
}
@@ -152,6 +156,27 @@ public class TechnicalDebtXMLImporter implements ServerExtension {
}
}
+ private Characteristic processDeprecatedFunctionsOnRequirement(Characteristic characteristic, ValidationMessages messages) {
+ CharacteristicProperty function = characteristic.getProperty(TechnicalDebtRequirement.PROPERTY_REMEDIATION_FUNCTION);
+ if (function != null) {
+ if ("linear_threshold".equals(function.getTextValue())) {
+ function.setTextValue(TechnicalDebtRequirement.FUNCTION_LINEAR);
+ CharacteristicProperty offset = characteristic.getProperty(TechnicalDebtRequirement.PROPERTY_OFFSET);
+ offset.setValue(0d);
+
+ String message = String.format("Linear with threshold function is no more used, the function of the requirement '%s' is replaced by linear.", characteristic.getRule());
+ LOG.warn(message);
+ messages.addWarningText(message);
+ } else if ("constant_resource".equals(function.getTextValue())) {
+ String message = String.format("Constant / file function is no more used, requirement '%s' is ignore.", characteristic.getRule());
+ LOG.warn(message);
+ messages.addWarningText(message);
+ return null;
+ }
+ }
+ return characteristic;
+ }
+
private void processProperty(Characteristic characteristic, SMInputCursor cursor, ValidationMessages messages) throws XMLStreamException {
SMInputCursor c = cursor.childElementCursor();
String key = null;
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/AbstractFunction.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/AbstractFunction.java
deleted file mode 100644
index 86146993b1b..00000000000
--- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/AbstractFunction.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.technicaldebt.functions;
-
-import org.sonar.api.issue.Issue;
-import org.sonar.api.rules.Violation;
-import org.sonar.core.technicaldebt.TechnicalDebtConverter;
-import org.sonar.core.technicaldebt.TechnicalDebtRequirement;
-
-import java.util.Collection;
-
-public abstract class AbstractFunction implements Function {
-
- private TechnicalDebtConverter converter;
-
- public AbstractFunction(TechnicalDebtConverter converter) {
- this.converter = converter;
- }
-
- protected TechnicalDebtConverter getConverter() {
- return converter;
- }
-
- public abstract String getKey();
-
- public abstract double costInHours(TechnicalDebtRequirement requirement, Collection<Violation> violations);
-
- public abstract long costInMinutes(TechnicalDebtRequirement requirement, Issue issue);
-
- protected long factorInMinutes(TechnicalDebtRequirement requirement) {
- return getConverter().toMinutes(requirement.getRemediationFactor());
- }
-
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/ConstantFunction.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/ConstantFunction.java
deleted file mode 100644
index 7f92e8604b7..00000000000
--- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/ConstantFunction.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.technicaldebt.functions;
-
-import org.sonar.api.issue.Issue;
-import org.sonar.api.rules.Violation;
-import org.sonar.core.technicaldebt.TechnicalDebtConverter;
-import org.sonar.core.technicaldebt.TechnicalDebtRequirement;
-
-import java.util.Collection;
-
-public final class ConstantFunction extends AbstractFunction {
-
- public static final String FUNCTION_CONSTANT_RESOURCE = "constant_resource";
-
- public ConstantFunction(TechnicalDebtConverter converter) {
- super(converter);
- }
-
- public String getKey() {
- return FUNCTION_CONSTANT_RESOURCE;
- }
-
- public double costInHours(TechnicalDebtRequirement requirement, Collection<Violation> violations) {
- double cost = 0.0;
- if (!violations.isEmpty()) {
- cost = getConverter().toDays(requirement.getRemediationFactor());
- }
- return cost;
- }
-
- public long costInMinutes(TechnicalDebtRequirement requirement, Issue issue) {
- return factorInMinutes(requirement);
- }
-
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/Function.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/Function.java
deleted file mode 100644
index 65a37918499..00000000000
--- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/Function.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.technicaldebt.functions;
-
-import org.sonar.api.BatchComponent;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.rules.Violation;
-import org.sonar.core.technicaldebt.TechnicalDebtRequirement;
-
-import java.util.Collection;
-
-public interface Function extends BatchComponent {
-
- String getKey();
-
- double costInHours(TechnicalDebtRequirement requirement, Collection<Violation> violations);
-
- long costInMinutes(TechnicalDebtRequirement requirement, Issue issue);
-
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/Functions.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/Functions.java
deleted file mode 100644
index da43d06a508..00000000000
--- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/Functions.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.technicaldebt.functions;
-
-import com.google.common.collect.Maps;
-import org.sonar.api.BatchComponent;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.rules.Violation;
-import org.sonar.core.technicaldebt.TechnicalDebtRequirement;
-
-import java.util.Collection;
-import java.util.Map;
-
-public class Functions implements BatchComponent {
-
- private final Map<String, Function> functionsByKey = Maps.newHashMap();
-
- public Functions(final Function[] functions) {
- for (Function function : functions) {
- functionsByKey.put(function.getKey(), function);
- }
- }
-
- Function getFunction(String key) {
- return functionsByKey.get(key);
- }
-
- public Function getFunction(TechnicalDebtRequirement requirement) {
- return getFunction(requirement.getRemediationFunction());
- }
-
- public double costInHours(TechnicalDebtRequirement requirement, Collection<Violation> violations) {
- return getFunction(requirement).costInHours(requirement, violations);
- }
-
- public long costInMinutes(TechnicalDebtRequirement requirement, Issue issue) {
- return getFunction(requirement).costInMinutes(requirement, issue);
- }
-
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearFunction.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearFunction.java
deleted file mode 100644
index d351372576b..00000000000
--- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearFunction.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.technicaldebt.functions;
-
-import org.sonar.api.issue.Issue;
-import org.sonar.api.rules.Violation;
-import org.sonar.core.technicaldebt.TechnicalDebtConverter;
-import org.sonar.core.technicaldebt.TechnicalDebtRequirement;
-
-import java.util.Collection;
-
-public class LinearFunction extends AbstractFunction {
-
- public static final String FUNCTION_LINEAR = "linear";
-
- public static final double DEFAULT_VIOLATION_COST = 1.0;
-
- public LinearFunction(TechnicalDebtConverter converter) {
- super(converter);
- }
-
- public String getKey() {
- return FUNCTION_LINEAR;
- }
-
- public double costInHours(TechnicalDebtRequirement requirement, Collection<Violation> violations) {
- double points = 0.0;
- for (Violation violation : violations) {
- Double effortToFix = violation.getCost();
- points += effortToFix != null ? effortToFix : DEFAULT_VIOLATION_COST;
- }
- return points * getConverter().toDays(requirement.getRemediationFactor());
- }
-
- public long costInMinutes(TechnicalDebtRequirement requirement, Issue issue) {
- Double effortToFix = issue.effortToFix();
- double points = effortToFix != null ? effortToFix : DEFAULT_VIOLATION_COST;
- return Double.valueOf(points * factorInMinutes(requirement)).longValue();
- }
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearWithOffsetFunction.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearWithOffsetFunction.java
deleted file mode 100644
index 890dc779ec3..00000000000
--- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearWithOffsetFunction.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.technicaldebt.functions;
-
-import org.sonar.api.rules.Violation;
-import org.sonar.core.technicaldebt.TechnicalDebtConverter;
-import org.sonar.core.technicaldebt.TechnicalDebtRequirement;
-
-import java.util.Collection;
-
-public final class LinearWithOffsetFunction extends LinearFunction {
-
- public static final String FUNCTION_LINEAR_WITH_OFFSET = "linear_offset";
-
- public LinearWithOffsetFunction(TechnicalDebtConverter converter) {
- super(converter);
- }
-
- public String getKey() {
- return FUNCTION_LINEAR_WITH_OFFSET;
- }
-
- public double costInHours(TechnicalDebtRequirement requirement, Collection<Violation> violations) {
- if (violations.isEmpty()) {
- return 0.0;
- }
- double minimunCost = getConverter().toDays(requirement.getOffset());
- return minimunCost + super.costInHours(requirement, violations);
- }
-
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearWithThresholdFunction.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearWithThresholdFunction.java
deleted file mode 100644
index f8fc198556e..00000000000
--- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearWithThresholdFunction.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.technicaldebt.functions;
-
-import org.sonar.api.rules.Violation;
-import org.sonar.core.technicaldebt.TechnicalDebtConverter;
-import org.sonar.core.technicaldebt.TechnicalDebtRequirement;
-
-import java.util.Collection;
-
-public final class LinearWithThresholdFunction extends LinearFunction {
-
- public static final String FUNCTION_LINEAR_WITH_THRESHOLD = "linear_threshold";
-
- public LinearWithThresholdFunction(TechnicalDebtConverter converter) {
- super(converter);
- }
-
- public String getKey() {
- return FUNCTION_LINEAR_WITH_THRESHOLD;
- }
-
- public double costInHours(TechnicalDebtRequirement requirement, Collection<Violation> violations) {
- if (violations.isEmpty()) {
- return 0.0;
- }
- double thresholdCost = getConverter().toDays(requirement.getOffset());
- double violationsCost = super.costInHours(requirement, violations);
- return violationsCost > thresholdCost ? violationsCost : thresholdCost;
- }
-
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/package-info.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/package-info.java
deleted file mode 100644
index dfc07e1508a..00000000000
--- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.core.technicaldebt.functions;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtCalculatorTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtCalculatorTest.java
index ef3289b938f..2da03d4f46a 100644
--- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtCalculatorTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtCalculatorTest.java
@@ -19,192 +19,104 @@
*/
package org.sonar.core.technicaldebt;
-import com.google.common.collect.ListMultimap;
-import org.apache.commons.lang.time.DateUtils;
import org.junit.Before;
import org.junit.Test;
-import org.sonar.api.batch.DecoratorContext;
-import org.sonar.api.issue.Issue;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
import org.sonar.api.issue.internal.DefaultIssue;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.MeasuresFilter;
-import org.sonar.api.qualitymodel.Characteristic;
import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.Violation;
-import org.sonar.core.technicaldebt.functions.Functions;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-
-import static com.google.common.collect.Lists.newArrayList;
import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
+@RunWith(MockitoJUnitRunner.class)
public class TechnicalDebtCalculatorTest {
- private static final Date NOW = new Date(System.currentTimeMillis());
- private static final Date YESTERDAY = DateUtils.addDays(NOW, -1);
- private static final Date LAST_MONTH = DateUtils.addMonths(NOW, -1);
-
- private TechnicalDebtModel technicalDebtModel;
- private Functions functions;
- private TechnicalDebtCalculator remediationCostCalculator;
-
- @Before
- public void initMocks() {
- technicalDebtModel = mock(TechnicalDebtModel.class);
- functions = mock(Functions.class);
- TechnicalDebtConverter converter = mock(TechnicalDebtConverter.class);
- remediationCostCalculator = new TechnicalDebtCalculator(technicalDebtModel, functions, converter);
- }
-
- @Test
- public void group_violations_by_requirement() throws Exception {
-
- TechnicalDebtRequirement requirement1 = mock(TechnicalDebtRequirement.class);
- TechnicalDebtRequirement requirement2 = mock(TechnicalDebtRequirement.class);
+ @Mock
+ TechnicalDebtModel technicalDebtModel;
- Violation violation1 = buildViolation("rule1", "repo1", NOW);
- Violation violation2 = buildViolation("rule1", "repo1", NOW);
- Violation violation3 = buildViolation("rule2", "repo2", NOW);
- Violation violation4 = buildViolation("unmatchable", "repo2", NOW);
+ @Mock
+ TechnicalDebtConverter converter;
- List<Violation> violations = newArrayList(violation1, violation2, violation3, violation4);
+ WorkUnit tenMinutes = WorkUnit.create(10d, WorkUnit.MINUTES);
+ WorkUnit fiveMinutes = WorkUnit.create(5d, WorkUnit.MINUTES);
- when(technicalDebtModel.getRequirementByRule("repo1", "rule1")).thenReturn(requirement1);
- when(technicalDebtModel.getRequirementByRule("repo2", "rule2")).thenReturn(requirement2);
+ TechnicalDebtCalculator remediationCostCalculator;
- DecoratorContext context = mock(DecoratorContext.class);
- when(context.getViolations()).thenReturn(violations);
-
- ListMultimap<TechnicalDebtRequirement, Violation> groupedViolations = remediationCostCalculator.groupViolations(context);
+ @Before
+ public void before() {
+ when(converter.toMinutes(tenMinutes)).thenReturn(10l);
+ when(converter.toMinutes(fiveMinutes)).thenReturn(5l);
- assertThat(groupedViolations.keySet().size()).isEqualTo(2);
- assertThat(groupedViolations.get(requirement1)).containsExactly(violation1, violation2);
- assertThat(groupedViolations.get(requirement2)).containsExactly(violation3);
+ remediationCostCalculator = new TechnicalDebtCalculator(technicalDebtModel, converter);
}
@Test
- public void add_cost_with_no_parent() throws Exception {
-
- double requirementCost = 1.0;
+ public void calcul_technical_debt() throws Exception {
+ DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(RuleKey.of("squid", "AvoidCycle"));
TechnicalDebtRequirement requirement = mock(TechnicalDebtRequirement.class);
- when(requirement.getParent()).thenReturn(null);
+ Mockito.when(requirement.getRemediationFactor()).thenReturn(tenMinutes);
+ Mockito.when(requirement.getOffset()).thenReturn(fiveMinutes);
+ when(technicalDebtModel.getRequirementByRule("squid", "AvoidCycle")).thenReturn(requirement);
- remediationCostCalculator.updateRequirementCosts(requirement, requirementCost);
+ remediationCostCalculator.calculTechnicalDebt(issue);
- assertThat(remediationCostCalculator.getRequirementCosts().get(requirement)).isEqualTo(requirementCost);
- assertThat(remediationCostCalculator.getTotal()).isEqualTo(requirementCost);
+ verify(converter).fromMinutes(10l + 5l);
}
@Test
- public void add_cost_and_propagate_to_parents() throws Exception {
-
- double requirementCost = 1.0;
-
- TechnicalDebtCharacteristic parentCharacteristic = new TechnicalDebtCharacteristic(Characteristic.create());
-
- TechnicalDebtCharacteristic characteristic = new TechnicalDebtCharacteristic(Characteristic.create(), parentCharacteristic);
+ public void calcul_technical_debt_with_effort_to_fix() throws Exception {
+ DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(RuleKey.of("squid", "AvoidCycle")).setEffortToFix(2d);
TechnicalDebtRequirement requirement = mock(TechnicalDebtRequirement.class);
- when(requirement.getParent()).thenReturn(characteristic);
+ Mockito.when(requirement.getRemediationFactor()).thenReturn(tenMinutes);
+ Mockito.when(requirement.getOffset()).thenReturn(fiveMinutes);
+ when(technicalDebtModel.getRequirementByRule("squid", "AvoidCycle")).thenReturn(requirement);
- remediationCostCalculator.updateRequirementCosts(requirement, requirementCost);
+ remediationCostCalculator.calculTechnicalDebt(issue);
- assertThat(remediationCostCalculator.getRequirementCosts().get(requirement)).isEqualTo(requirementCost);
- assertThat(remediationCostCalculator.getCharacteristicCosts().get(characteristic)).isEqualTo(requirementCost);
- assertThat(remediationCostCalculator.getCharacteristicCosts().get(parentCharacteristic)).isEqualTo(requirementCost);
+ verify(converter).fromMinutes(10l * 2 + 5l);
}
@Test
- public void compute_totals_costs() throws Exception {
-
- TechnicalDebtRequirement requirement1 = mock(TechnicalDebtRequirement.class);
- TechnicalDebtRequirement requirement2 = mock(TechnicalDebtRequirement.class);
+ public void calcul_technical_debt_with_no_offset() throws Exception {
+ DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(RuleKey.of("squid", "AvoidCycle")).setEffortToFix(2d);
- Violation violation1 = buildViolation("rule1", "repo1", NOW);
- Violation violation2 = buildViolation("rule1", "repo1", NOW);
- Violation violation3 = buildViolation("rule2", "repo2", YESTERDAY);
- Violation violation4 = buildViolation("rule2", "repo2", LAST_MONTH);
-
- List<Violation> violations = newArrayList(violation1, violation2, violation3, violation4);
-
- when(technicalDebtModel.getRequirementByRule("repo1", "rule1")).thenReturn(requirement1);
- when(technicalDebtModel.getRequirementByRule("repo2", "rule2")).thenReturn(requirement2);
- when(technicalDebtModel.getAllRequirements()).thenReturn(newArrayList(requirement1, requirement2));
-
- when(functions.costInHours(any(TechnicalDebtRequirement.class), any(Collection.class))).thenReturn(1.0);
-
- DecoratorContext context = mock(DecoratorContext.class);
- when(context.getViolations()).thenReturn(violations);
- when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.EMPTY_LIST);
+ TechnicalDebtRequirement requirement = mock(TechnicalDebtRequirement.class);
+ Mockito.when(requirement.getRemediationFactor()).thenReturn(tenMinutes);
+ Mockito.when(requirement.getOffset()).thenReturn(null);
+ when(technicalDebtModel.getRequirementByRule("squid", "AvoidCycle")).thenReturn(requirement);
- remediationCostCalculator.compute(context);
+ remediationCostCalculator.calculTechnicalDebt(issue);
- assertThat(remediationCostCalculator.getTotal()).isEqualTo(2.0);
- assertThat(remediationCostCalculator.getRequirementCosts().get(requirement1)).isEqualTo(1.0);
- assertThat(remediationCostCalculator.getRequirementCosts().get(requirement2)).isEqualTo(1.0);
+ verify(converter).fromMinutes(10l * 2 + 0l);
}
@Test
- public void compute_totals_costs_from_children() throws Exception {
- TechnicalDebtCharacteristic parentCharacteristic = new TechnicalDebtCharacteristic(Characteristic.create());
- TechnicalDebtRequirement requirement1 = new TechnicalDebtRequirement(Characteristic.create(), parentCharacteristic);;
-
- Violation violation1 = buildViolation("rule1", "repo1", NOW);
- Violation violation2 = buildViolation("rule1", "repo1", NOW);
- Violation violation3 = buildViolation("rule2", "repo2", YESTERDAY);
- Violation violation4 = buildViolation("rule2", "repo2", LAST_MONTH);
-
- List<Violation> violations = newArrayList(violation1, violation2, violation3, violation4);
-
- when(technicalDebtModel.getRequirementByRule("repo1", "rule1")).thenReturn(requirement1);
- when(technicalDebtModel.getAllRequirements()).thenReturn(newArrayList(requirement1));
+ public void calcul_technical_debt_with_no_factor() throws Exception {
+ DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(RuleKey.of("squid", "AvoidCycle")).setEffortToFix(2d);
- when(functions.costInHours(any(TechnicalDebtRequirement.class), any(Collection.class))).thenReturn(1.0);
-
- DecoratorContext context = mock(DecoratorContext.class);
- when(context.getViolations()).thenReturn(violations);
-
- Measure measure = new Measure().setCharacteristic(requirement1.toCharacteristic()).setValue(5.0);
- when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(newArrayList(measure));
-
- remediationCostCalculator.compute(context);
-
- assertThat(remediationCostCalculator.getTotal()).isEqualTo(6.0);
- assertThat(remediationCostCalculator.getRequirementCosts().get(requirement1)).isEqualTo(6.0);
- }
-
- @Test
- public void technical_debt_from_one_issue() throws Exception {
- DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(RuleKey.of("squid", "AvoidCycle"));
TechnicalDebtRequirement requirement = mock(TechnicalDebtRequirement.class);
+ Mockito.when(requirement.getRemediationFactor()).thenReturn(null);
+ Mockito.when(requirement.getOffset()).thenReturn(fiveMinutes);
when(technicalDebtModel.getRequirementByRule("squid", "AvoidCycle")).thenReturn(requirement);
- when(functions.costInMinutes(eq(requirement), eq(issue))).thenReturn(10L);
remediationCostCalculator.calculTechnicalDebt(issue);
- verify(functions).costInMinutes(eq(requirement), eq(issue));
+
+ verify(converter).fromMinutes(0l * 2 + 5l);
}
@Test
- public void no_technical_debt_from_one_issue_if_requirement_not_found() throws Exception {
+ public void no_technical_debt_if_requirement_not_found() throws Exception {
DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(RuleKey.of("squid", "AvoidCycle"));
when(technicalDebtModel.getRequirementByRule("squid", "AvoidCycle")).thenReturn(null);
assertThat(remediationCostCalculator.calculTechnicalDebt(issue)).isNull();
- verify(functions, never()).costInMinutes(any(TechnicalDebtRequirement.class), any(Issue.class));
+ verify(converter, never()).fromMinutes(anyLong());
}
- private Violation buildViolation(String ruleKey, String repositoryKey, Date creationDate) {
- Violation violation = mock(Violation.class);
- stub(violation.getRule()).toReturn(Rule.create(repositoryKey, ruleKey));
- stub(violation.getCreatedAt()).toReturn(creationDate);
- return violation;
- }
}
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtConverterTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtConverterTest.java
index d72511e1a29..a2c04fa960c 100644
--- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtConverterTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtConverterTest.java
@@ -40,13 +40,6 @@ public class TechnicalDebtConverterTest {
}
@Test
- public void convert_work_unit_to_days() {
- assertThat(converter.toDays(WorkUnit.create(6.0, WorkUnit.DAYS))).isEqualTo(6.0);
- assertThat(converter.toDays(WorkUnit.create(6.0, WorkUnit.HOURS))).isEqualTo(6.0 / 12.0);
- assertThat(converter.toDays(WorkUnit.create(60.0, WorkUnit.MINUTES))).isEqualTo(1.0 / 12.0);
- }
-
- @Test
public void concert_work_unit_to_minutes() {
assertThat(converter.toMinutes(WorkUnit.create(2.0, WorkUnit.DAYS))).isEqualTo(2 * 12 * 60L);
assertThat(converter.toMinutes(WorkUnit.create(6.0, WorkUnit.HOURS))).isEqualTo(6 * 60L);
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtRequirementTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtRequirementTest.java
index 1cf6f740e25..f56e86072f8 100644
--- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtRequirementTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtRequirementTest.java
@@ -21,95 +21,90 @@ package org.sonar.core.technicaldebt;
import org.junit.Test;
import org.sonar.api.qualitymodel.Characteristic;
-import org.sonar.core.technicaldebt.functions.ConstantFunction;
-import org.sonar.core.technicaldebt.functions.LinearFunction;
-import org.sonar.core.technicaldebt.functions.LinearWithOffsetFunction;
-import org.sonar.core.technicaldebt.functions.LinearWithThresholdFunction;
-import static org.hamcrest.Matchers.nullValue;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
+import static org.fest.assertions.Assertions.assertThat;
public class TechnicalDebtRequirementTest {
@Test
- public void defaultFactor() {
+ public void default_factor() {
Characteristic persistedRequirement = Characteristic.createByName("Efficiency");
+
TechnicalDebtRequirement requirement = new TechnicalDebtRequirement(persistedRequirement, null);
- assertThat(requirement.getRemediationFactor().getValue(), is(WorkUnit.DEFAULT_VALUE));
- assertThat(requirement.getRemediationFactor().getUnit(), is(WorkUnit.DEFAULT_UNIT));
+ assertThat(requirement.getRemediationFactor().getValue()).isEqualTo(WorkUnit.DEFAULT_VALUE);
+ assertThat(requirement.getRemediationFactor().getUnit()).isEqualTo(WorkUnit.DEFAULT_UNIT);
}
@Test
- public void testOverriddenFactor() {
+ public void overridde_factor() {
Characteristic persistedRequirement = Characteristic.createByName("Efficiency");
persistedRequirement.setProperty(TechnicalDebtRequirement.PROPERTY_REMEDIATION_FACTOR, 3.14);
+
TechnicalDebtRequirement requirement = new TechnicalDebtRequirement(persistedRequirement, null);
- assertThat(requirement.getRemediationFactor().getValue(), is(3.14));
- assertThat(requirement.getRemediationFactor().getUnit(), is(WorkUnit.DAYS));
+ assertThat(requirement.getRemediationFactor().getValue()).isEqualTo(3.14);
+ assertThat(requirement.getRemediationFactor().getUnit()).isEqualTo(WorkUnit.DAYS);
}
@Test
- public void defaultFunctionIsLinear() {
+ public void default_function_is_linear() {
Characteristic persistedRequirement = Characteristic.createByName("Efficiency");
+
TechnicalDebtRequirement requirement = new TechnicalDebtRequirement(persistedRequirement, null);
- assertThat(requirement.getRemediationFunction(), is(LinearFunction.FUNCTION_LINEAR));
- assertThat(requirement.getOffset(), is(nullValue()));
+ assertThat(requirement.getRemediationFunction()).isEqualTo(TechnicalDebtRequirement.FUNCTION_LINEAR);
+ assertThat(requirement.getOffset()).isNull();
}
@Test
- public void testOverriddenFunction() {
+ public void linear() {
Characteristic persistedRequirement = Characteristic.createByName("Efficiency");
- persistedRequirement.setProperty(TechnicalDebtRequirement.PROPERTY_REMEDIATION_FUNCTION, ConstantFunction.FUNCTION_CONSTANT_RESOURCE);
+ persistedRequirement.setProperty(TechnicalDebtRequirement.PROPERTY_REMEDIATION_FUNCTION, TechnicalDebtRequirement.FUNCTION_LINEAR);
+ persistedRequirement.setProperty(TechnicalDebtRequirement.PROPERTY_REMEDIATION_FACTOR, 3.14);
+
TechnicalDebtRequirement requirement = new TechnicalDebtRequirement(persistedRequirement, null);
- assertThat(requirement.getRemediationFunction(), is(ConstantFunction.FUNCTION_CONSTANT_RESOURCE));
+ assertThat(requirement.getRemediationFunction()).isEqualTo(TechnicalDebtRequirement.FUNCTION_LINEAR);
+ assertThat(requirement.getRemediationFactor().getValue()).isEqualTo(3.14);
+ assertThat(requirement.getRemediationFactor().getUnit()).isEqualTo(WorkUnit.DAYS);
+ assertThat(requirement.getOffset()).isNull();
}
@Test
- public void testDefaultLinearWithOffset() {
+ public void default_linear_with_offset() {
Characteristic persistedRequirement = Characteristic.createByName("Efficiency");
- persistedRequirement.setProperty(TechnicalDebtRequirement.PROPERTY_REMEDIATION_FUNCTION, LinearWithOffsetFunction.FUNCTION_LINEAR_WITH_OFFSET);
+ persistedRequirement.setProperty(TechnicalDebtRequirement.PROPERTY_REMEDIATION_FUNCTION, TechnicalDebtRequirement.FUNCTION_LINEAR_WITH_OFFSET);
+
TechnicalDebtRequirement requirement = new TechnicalDebtRequirement(persistedRequirement, null);
- assertThat(requirement.getRemediationFunction(), is(LinearWithOffsetFunction.FUNCTION_LINEAR_WITH_OFFSET));
- assertThat(requirement.getRemediationFactor().getValue(), is(WorkUnit.DEFAULT_VALUE));
- assertThat(requirement.getRemediationFactor().getUnit(), is(WorkUnit.DEFAULT_UNIT));
- assertThat(requirement.getOffset().getValue(), is(WorkUnit.DEFAULT_VALUE));
- assertThat(requirement.getOffset().getUnit(), is(WorkUnit.DEFAULT_UNIT));
+ assertThat(requirement.getRemediationFunction()).isEqualTo(TechnicalDebtRequirement.FUNCTION_LINEAR_WITH_OFFSET);
+ assertThat(requirement.getRemediationFactor().getValue()).isEqualTo(WorkUnit.DEFAULT_VALUE);
+ assertThat(requirement.getRemediationFactor().getUnit()).isEqualTo(WorkUnit.DEFAULT_UNIT);
+ assertThat(requirement.getOffset().getValue()).isEqualTo(WorkUnit.DEFAULT_VALUE);
+ assertThat(requirement.getOffset().getUnit()).isEqualTo(WorkUnit.DEFAULT_UNIT);
}
@Test
- public void testCustomizedLinearWithOffset() {
+ public void linear_with_offset() {
Characteristic persistedRequirement = Characteristic.createByName("Efficiency");
- persistedRequirement.setProperty(TechnicalDebtRequirement.PROPERTY_REMEDIATION_FUNCTION, LinearWithOffsetFunction.FUNCTION_LINEAR_WITH_OFFSET);
+ persistedRequirement.setProperty(TechnicalDebtRequirement.PROPERTY_REMEDIATION_FUNCTION, TechnicalDebtRequirement.FUNCTION_LINEAR_WITH_OFFSET);
persistedRequirement.setProperty(TechnicalDebtRequirement.PROPERTY_OFFSET, 5.0);
persistedRequirement.addProperty(persistedRequirement.getProperty(TechnicalDebtRequirement.PROPERTY_OFFSET).setTextValue("h"));
- TechnicalDebtRequirement requirement = new TechnicalDebtRequirement(persistedRequirement, null);
- assertThat(requirement.getRemediationFunction(), is(LinearWithOffsetFunction.FUNCTION_LINEAR_WITH_OFFSET));
- assertThat(requirement.getOffset().getValue(), is(5.0));
- assertThat(requirement.getOffset().getUnit(), is(WorkUnit.HOURS));
- }
- @Test
- public void testDefaultLinearWithThreshold() {
- Characteristic persistedRequirement = Characteristic.createByName("Efficiency");
- persistedRequirement.setProperty(TechnicalDebtRequirement.PROPERTY_REMEDIATION_FUNCTION, LinearWithThresholdFunction.FUNCTION_LINEAR_WITH_THRESHOLD);
TechnicalDebtRequirement requirement = new TechnicalDebtRequirement(persistedRequirement, null);
- assertThat(requirement.getRemediationFunction(), is(LinearWithThresholdFunction.FUNCTION_LINEAR_WITH_THRESHOLD));
- assertThat(requirement.getRemediationFactor().getValue(), is(WorkUnit.DEFAULT_VALUE));
- assertThat(requirement.getRemediationFactor().getUnit(), is(WorkUnit.DEFAULT_UNIT));
- assertThat(requirement.getOffset().getValue(), is(WorkUnit.DEFAULT_VALUE));
- assertThat(requirement.getOffset().getUnit(), is(WorkUnit.DEFAULT_UNIT));
+ assertThat(requirement.getRemediationFunction()).isEqualTo(TechnicalDebtRequirement.FUNCTION_LINEAR_WITH_OFFSET);
+ assertThat(requirement.getOffset().getValue()).isEqualTo(5.0);
+ assertThat(requirement.getOffset().getUnit()).isEqualTo(WorkUnit.HOURS);
}
@Test
- public void testCustomizedLinearWithThreshold() {
+ public void constant_per_issue() {
Characteristic persistedRequirement = Characteristic.createByName("Efficiency");
- persistedRequirement.setProperty(TechnicalDebtRequirement.PROPERTY_REMEDIATION_FUNCTION, LinearWithThresholdFunction.FUNCTION_LINEAR_WITH_THRESHOLD);
+ persistedRequirement.setProperty(TechnicalDebtRequirement.PROPERTY_REMEDIATION_FUNCTION, TechnicalDebtRequirement.FUNCTION_CONSTANT_PER_ISSUE);
persistedRequirement.setProperty(TechnicalDebtRequirement.PROPERTY_OFFSET, 5.0);
persistedRequirement.addProperty(persistedRequirement.getProperty(TechnicalDebtRequirement.PROPERTY_OFFSET).setTextValue("h"));
+
TechnicalDebtRequirement requirement = new TechnicalDebtRequirement(persistedRequirement, null);
- assertThat(requirement.getRemediationFunction(), is(LinearWithThresholdFunction.FUNCTION_LINEAR_WITH_THRESHOLD));
- assertThat(requirement.getOffset().getValue(), is(5.0));
- assertThat(requirement.getOffset().getUnit(), is(WorkUnit.HOURS));
+ assertThat(requirement.getRemediationFunction()).isEqualTo(TechnicalDebtRequirement.FUNCTION_CONSTANT_PER_ISSUE);
+ assertThat(requirement.getRemediationFactor()).isNull();
+ assertThat(requirement.getOffset().getValue()).isEqualTo(5.0);
+ assertThat(requirement.getOffset().getUnit()).isEqualTo(WorkUnit.HOURS);
}
+
}
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest.java
index cac08a416cb..6e9c94e246a 100644
--- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest.java
@@ -22,7 +22,6 @@ package org.sonar.core.technicaldebt;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import com.google.common.io.Resources;
-import org.fest.assertions.Assertions;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mockito;
@@ -35,13 +34,15 @@ import org.sonar.api.utils.ValidationMessages;
import java.io.IOException;
+import static org.fest.assertions.Assertions.assertThat;
+
public class TechnicalDebtXMLImporterTest {
@Test
- public void shouldImportXML() {
+ public void import_xml_with_linear_function() {
TechnicalDebtRuleCache technicalDebtRuleCache = mockRuleCache();
- String xml = getFileContent("shouldImportXML.xml");
+ String xml = getFileContent("shouldImportXML_with_linear.xml");
ValidationMessages messages = ValidationMessages.create();
Model sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache);
@@ -50,6 +51,48 @@ public class TechnicalDebtXMLImporterTest {
}
@Test
+ public void import_xml_with_linear_with_offset() {
+ TechnicalDebtRuleCache technicalDebtRuleCache = mockRuleCache();
+
+ String xml = getFileContent("shouldImportXML_with_linear_with_offset.xml");
+
+ ValidationMessages messages = ValidationMessages.create();
+ Model sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache);
+
+ checkXmlCorrectlyImported(sqale, 1.0, messages);
+ }
+
+ @Test
+ public void convert_deprecated_linear_with_threshold_function_by_linear_function() {
+ TechnicalDebtRuleCache technicalDebtRuleCache = mockRuleCache();
+
+ String xml = getFileContent("shouldImportXML_with_deprecated_linear_with_threshold.xml");
+
+ ValidationMessages messages = ValidationMessages.create();
+ Model sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache);
+
+ checkXmlCorrectlyImported(sqale, 0.0, messages);
+ assertThat(messages.getWarnings()).hasSize(1);
+ }
+
+ @Test
+ public void ignore_deprecated_constant_per_file_function() {
+ TechnicalDebtRuleCache technicalDebtRuleCache = mockRuleCache();
+
+ String xml = getFileContent("shouldImportXML_with_deprecated_constant_per_file.xml");
+
+ ValidationMessages messages = ValidationMessages.create();
+ Model sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache);
+
+ assertThat(messages.getWarnings()).hasSize(1);
+
+ // characteristics
+ assertThat(sqale.getRootCharacteristics()).hasSize(1);
+ Characteristic efficiency = sqale.getCharacteristicByKey("EFFICIENCY");
+ assertThat(efficiency.getChildren()).isEmpty();
+ }
+
+ @Test
public void shouldBadlyFormattedImportXML() {
TechnicalDebtRuleCache technicalDebtRuleCache = mockRuleCache();
String xml = getFileContent("shouldImportXML_badly-formatted.xml");
@@ -68,13 +111,13 @@ public class TechnicalDebtXMLImporterTest {
Model sqale = new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache);
- Assertions.assertThat(messages.getWarnings()).hasSize(1);
+ assertThat(messages.getWarnings()).hasSize(1);
// characteristics
- Assertions.assertThat(sqale.getRootCharacteristics()).hasSize(1);
+ assertThat(sqale.getRootCharacteristics()).hasSize(1);
Characteristic efficiency = sqale.getCharacteristicByKey("EFFICIENCY");
- Assertions.assertThat(efficiency.getChildren()).isEmpty();
- Assertions.assertThat(messages.getWarnings().get(0)).contains("findbugs");
+ assertThat(efficiency.getChildren()).isEmpty();
+ assertThat(messages.getWarnings().get(0)).contains("findbugs");
}
@Test
@@ -87,8 +130,8 @@ public class TechnicalDebtXMLImporterTest {
new TechnicalDebtXMLImporter().importXML(xml, messages, technicalDebtRuleCache);
- Assertions.assertThat(messages.getErrors()).hasSize(1);
- Assertions.assertThat(messages.getErrors().get(0)).isEqualTo("Cannot import value 'abc' for field factor - Expected a numeric value instead");
+ assertThat(messages.getErrors()).hasSize(1);
+ assertThat(messages.getErrors().get(0)).isEqualTo("Cannot import value 'abc' for field factor - Expected a numeric value instead");
}
private TechnicalDebtRuleCache mockRuleCache() {
@@ -98,23 +141,28 @@ public class TechnicalDebtXMLImporterTest {
}
private void checkXmlCorrectlyImported(Model sqale, ValidationMessages messages) {
+ checkXmlCorrectlyImported(sqale, null, messages);
+ }
+
+ private void checkXmlCorrectlyImported(Model sqale, Double offset, ValidationMessages messages) {
- Assertions.assertThat(messages.getErrors()).isEmpty();
- Assertions.assertThat(sqale.getName()).isEqualTo(TechnicalDebtModel.MODEL_NAME);
+ assertThat(messages.getErrors()).isEmpty();
+ assertThat(sqale.getName()).isEqualTo(TechnicalDebtModel.MODEL_NAME);
// characteristics
- Assertions.assertThat(sqale.getRootCharacteristics()).hasSize(2);
- Assertions.assertThat(sqale.getCharacteristicByKey("USABILITY").getDescription()).isEqualTo("Estimate usability");
+ assertThat(sqale.getRootCharacteristics()).hasSize(2);
+ assertThat(sqale.getCharacteristicByKey("USABILITY").getDescription()).isEqualTo("Estimate usability");
Characteristic efficiency = sqale.getCharacteristicByKey("EFFICIENCY");
- Assertions.assertThat(efficiency.getName()).isEqualTo("Efficiency");
+ assertThat(efficiency.getName()).isEqualTo("Efficiency");
// sub-characteristics
- Assertions.assertThat(efficiency.getChildren()).hasSize(1);
+ assertThat(efficiency.getChildren()).hasSize(1);
Characteristic requirement = efficiency.getChildren().get(0);
- Assertions.assertThat(requirement.getRule().getRepositoryKey()).isEqualTo("checkstyle");
- Assertions.assertThat(requirement.getRule().getKey()).isEqualTo("Regexp");
- Assertions.assertThat(requirement.getPropertyTextValue("function", null)).isEqualTo("linear");
- Assertions.assertThat(requirement.getPropertyValue("factor", null)).isEqualTo(3.2);
+ assertThat(requirement.getRule().getRepositoryKey()).isEqualTo("checkstyle");
+ assertThat(requirement.getRule().getKey()).isEqualTo("Regexp");
+ assertThat(requirement.getPropertyTextValue("remediationFunction", null)).isEqualTo("linear");
+ assertThat(requirement.getPropertyValue("remediationFactor", null)).isEqualTo(3.2);
+ assertThat(requirement.getPropertyValue("offset", null)).isEqualTo(offset);
}
private String getFileContent(String file) {
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/ConstantFunctionTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/ConstantFunctionTest.java
deleted file mode 100644
index 1a377123164..00000000000
--- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/ConstantFunctionTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.technicaldebt.functions;
-
-import com.google.common.collect.Lists;
-import org.hamcrest.core.Is;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.sonar.api.config.Settings;
-import org.sonar.api.issue.internal.DefaultIssue;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.Violation;
-import org.sonar.core.technicaldebt.TechnicalDebtConverter;
-import org.sonar.core.technicaldebt.TechnicalDebtRequirement;
-import org.sonar.core.technicaldebt.WorkUnit;
-
-import java.util.Collection;
-import java.util.Collections;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.when;
-
-public class ConstantFunctionTest {
-
- private TechnicalDebtRequirement requirement;
- private Function function;
-
- @Before
- public void before() {
- function = new ConstantFunction(new TechnicalDebtConverter(new Settings()));
- requirement = Mockito.mock(TechnicalDebtRequirement.class);
- Mockito.when(requirement.getRemediationFactor()).thenReturn(WorkUnit.createInDays(3.14));
- }
-
- @Test
- public void zero_if_no_violations() {
- Assert.assertThat(function.costInHours(requirement, Collections.<Violation>emptyList()), Is.is(0.0));
- }
-
- @Test
- public void count_as_if_single_violation() {
- Collection<Violation> violations = Lists.newArrayList();
-
- Rule rule = Rule.create("checkstyle", "foo", "Foo");
- violations.add(new Violation(rule));
- Assert.assertThat(function.costInHours(requirement, violations), Is.is(3.14));
-
- violations.add(new Violation(rule));
- Assert.assertThat(function.costInHours(requirement, violations), Is.is(3.14));
- }
-
- @Test
- public void cost_in_minutes() {
- when(requirement.getRemediationFactor()).thenReturn(WorkUnit.create(10d, WorkUnit.MINUTES));
- DefaultIssue issue = new DefaultIssue().setKey("ABCDE");
- assertThat(function.costInMinutes(requirement, issue)).isEqualTo(10L);
- }
-}
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/FunctionsTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/FunctionsTest.java
deleted file mode 100644
index e829e8e15e8..00000000000
--- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/FunctionsTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.technicaldebt.functions;
-
-import org.junit.Test;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class FunctionsTest {
-
- @Test
- public void register_functions() {
- Functions functions = new Functions(new Function[]{new LinearFunction(null), new LinearWithOffsetFunction(null),
- new ConstantFunction(null)});
- assertThat(functions.getFunction(LinearFunction.FUNCTION_LINEAR)).isInstanceOf(LinearFunction.class);
- assertThat(functions.getFunction(LinearWithOffsetFunction.FUNCTION_LINEAR_WITH_OFFSET)).isInstanceOf(LinearWithOffsetFunction.class);
- assertThat(functions.getFunction(ConstantFunction.FUNCTION_CONSTANT_RESOURCE)).isInstanceOf(ConstantFunction.class);
- assertThat(functions.getFunction("foo")).isNull();
- }
-}
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearFunctionTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearFunctionTest.java
deleted file mode 100644
index 1b2193298ac..00000000000
--- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearFunctionTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.technicaldebt.functions;
-
-import com.google.common.collect.Lists;
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.config.Settings;
-import org.sonar.api.issue.internal.DefaultIssue;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.Violation;
-import org.sonar.core.technicaldebt.TechnicalDebtConverter;
-import org.sonar.core.technicaldebt.TechnicalDebtRequirement;
-import org.sonar.core.technicaldebt.WorkUnit;
-
-import java.util.Collection;
-import java.util.Collections;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class LinearFunctionTest {
-
- private TechnicalDebtRequirement requirement;
- private Function function;
-
- @Before
- public void before() {
- Settings settings = new Settings();
- settings.setProperty(TechnicalDebtConverter.PROPERTY_HOURS_IN_DAY, 8);
- function = new LinearFunction(new TechnicalDebtConverter(settings));
-
- requirement = mock(TechnicalDebtRequirement.class);
- when(requirement.getRemediationFactor()).thenReturn(WorkUnit.createInDays(3.14));
- }
-
- @Test
- public void zero_if_no_violations() {
- assertThat(function.costInHours(requirement, Collections.<Violation>emptyList())).isEqualTo(0.0);
- }
-
- @Test
- public void count_every_violation() {
- Collection<Violation> violations = Lists.newArrayList();
-
- Rule rule = Rule.create("checkstyle", "foo", "Foo");
- violations.add(new Violation(rule));
- assertThat(function.costInHours(requirement, violations)).isEqualTo(3.14);
-
- violations.add(new Violation(rule));
- assertThat(function.costInHours(requirement, violations)).isEqualTo(3.14 * 2);
- }
-
- @Test
- public void use_points_when_available() {
- Collection<Violation> violations = Lists.newArrayList();
-
- Rule rule = Rule.create("checkstyle", "foo", "Foo");
- violations.add(new Violation(rule).setCost(20.5));
- violations.add(new Violation(rule).setCost(3.8));
- violations.add(new Violation(rule));
- assertThat(function.costInHours(requirement, violations)).isEqualTo(3.14 * (20.5 + 3.8 + 1));
- }
-
- @Test
- public void cost_in_minutes() {
- when(requirement.getRemediationFactor()).thenReturn(WorkUnit.create(10d, WorkUnit.MINUTES));
- DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setEffortToFix(2.0);
- assertThat(function.costInMinutes(requirement, issue)).isEqualTo(20L);
- }
-
- @Test
- public void cost_in_minutes_use_default_cost_when_no_effort_to_fix_on_issue() {
- when(requirement.getRemediationFactor()).thenReturn(WorkUnit.create(10d, WorkUnit.MINUTES));
- DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setEffortToFix(null);
- assertThat(function.costInMinutes(requirement, issue)).isEqualTo(10L);
- }
-}
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearWithOffsetFunctionTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearWithOffsetFunctionTest.java
deleted file mode 100644
index 1a0b6c03521..00000000000
--- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearWithOffsetFunctionTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.technicaldebt.functions;
-
-import com.google.common.collect.Lists;
-import org.hamcrest.core.Is;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.sonar.api.config.Settings;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.Violation;
-import org.sonar.core.technicaldebt.TechnicalDebtConverter;
-import org.sonar.core.technicaldebt.TechnicalDebtRequirement;
-import org.sonar.core.technicaldebt.WorkUnit;
-
-import java.util.Collection;
-import java.util.Collections;
-
-public class LinearWithOffsetFunctionTest {
-
- private TechnicalDebtRequirement requirement;
- private Function function = new LinearWithOffsetFunction(new TechnicalDebtConverter(new Settings()));
-
- @Before
- public void before() {
- requirement = Mockito.mock(TechnicalDebtRequirement.class);
- Mockito.when(requirement.getRemediationFactor()).thenReturn(WorkUnit.createInDays(3.14));
- Mockito.when(requirement.getOffset()).thenReturn(WorkUnit.createInDays(2.12));
- }
-
- @Test
- public void zeroIfNoViolations() {
- Assert.assertThat(function.costInHours(requirement, Collections.<Violation>emptyList()), Is.is(0.0));
- }
-
- @Test
- public void countEveryViolation() {
- Collection<Violation> violations = Lists.newArrayList();
-
- Rule rule = Rule.create("checkstyle", "foo", "Foo");
- violations.add(new Violation(rule));
- Assert.assertThat(function.costInHours(requirement, violations), Is.is(2.12 + 3.14));
-
- violations.add(new Violation(rule));
- Assert.assertThat(function.costInHours(requirement, violations), Is.is(2.12 + 3.14 * 2));
- }
-}
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearWithThresholdFunctionTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearWithThresholdFunctionTest.java
deleted file mode 100644
index 86c71479c05..00000000000
--- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearWithThresholdFunctionTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.technicaldebt.functions;
-
-import com.google.common.collect.Lists;
-import org.hamcrest.core.Is;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.sonar.api.config.Settings;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.Violation;
-import org.sonar.core.technicaldebt.TechnicalDebtConverter;
-import org.sonar.core.technicaldebt.TechnicalDebtRequirement;
-import org.sonar.core.technicaldebt.WorkUnit;
-
-import java.util.Collection;
-import java.util.Collections;
-
-public class LinearWithThresholdFunctionTest {
-
- private TechnicalDebtRequirement requirement;
- private Function function = new LinearWithThresholdFunction(new TechnicalDebtConverter(new Settings()));
-
- @Before
- public void before() {
- requirement = Mockito.mock(TechnicalDebtRequirement.class);
- Mockito.when(requirement.getRemediationFactor()).thenReturn(WorkUnit.createInDays(2.0));
- Mockito.when(requirement.getOffset()).thenReturn(WorkUnit.createInDays(5.0));
- }
-
- @Test
- public void zeroIfNoViolations() {
- Assert.assertThat(function.costInHours(requirement, Collections.<Violation>emptyList()), Is.is(0.0));
- }
-
- @Test
- public void countEveryViolationAndCheckThreshold() {
- Collection<Violation> violations = Lists.newArrayList();
-
- Rule rule = Rule.create("checkstyle", "foo", "Foo");
- violations.add(new Violation(rule));
- Assert.assertThat(function.costInHours(requirement, violations), Is.is(5.0));
-
- violations.add(new Violation(rule));
- Assert.assertThat(function.costInHours(requirement, violations), Is.is(5.0));
-
- violations.add(new Violation(rule));
- Assert.assertThat(function.costInHours(requirement, violations), Is.is(6.0));
- }
-}
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_badly-formatted.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_badly-formatted.xml
index 373959f1a72..e55fa2d003b 100644
--- a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_badly-formatted.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_badly-formatted.xml
@@ -19,13 +19,13 @@
<rule-key>Regexp
</rule-key>
<prop>
- <key>factor
+ <key>remediationFactor
</key>
<val>3.2
</val>
</prop>
<prop>
- <key>function
+ <key>remediationFunction
</key>
<txt>linear
</txt>
@@ -33,4 +33,4 @@
</chc>
</chc>
-</sqale> \ No newline at end of file
+</sqale>
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_with_deprecated_constant_per_file.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_with_deprecated_constant_per_file.xml
new file mode 100644
index 00000000000..2e13e2bd2a4
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_with_deprecated_constant_per_file.xml
@@ -0,0 +1,20 @@
+<sqale>
+ <chc>
+ <key>EFFICIENCY</key>
+ <name>Efficiency</name>
+ <!-- Should be ignored -->
+ <chc>
+ <rule-repo>checkstyle</rule-repo>
+ <rule-key>Regexp</rule-key>
+ <prop>
+ <key>remediationFactor</key>
+ <val>3.2</val>
+ </prop>
+ <prop>
+ <key>remediationFunction</key>
+ <txt>constant_resource</txt>
+ </prop>
+ </chc>
+ </chc>
+
+</sqale>
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_with_deprecated_linear_with_threshold.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_with_deprecated_linear_with_threshold.xml
new file mode 100644
index 00000000000..f46aea6e872
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_with_deprecated_linear_with_threshold.xml
@@ -0,0 +1,32 @@
+<sqale>
+ <chc>
+ <key>USABILITY</key>
+ <name>Usability</name>
+ <desc>Estimate usability</desc>
+ </chc>
+ <chc>
+ <key>EFFICIENCY</key>
+ <name>Efficiency</name>
+ <chc>
+ <rule-repo>checkstyle</rule-repo>
+ <rule-key>Regexp</rule-key>
+ <prop>
+ <key>remediationFunction</key>
+ <!-- Should be replaced by linear -->
+ <txt>linear_threshold</txt>
+ </prop>
+ <prop>
+ <key>remediationFactor</key>
+ <val>3.2</val>
+ <txt>h</txt>
+ </prop>
+ <!-- Should be ignored -->
+ <prop>
+ <key>offset</key>
+ <val>1.0</val>
+ <txt>h</txt>
+ </prop>
+ </chc>
+ </chc>
+
+</sqale>
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_with_linear.xml
index e4051894cb0..480df8f2d94 100644
--- a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_with_linear.xml
@@ -12,14 +12,14 @@
<rule-repo>checkstyle</rule-repo>
<rule-key>Regexp</rule-key>
<prop>
- <key>factor</key>
+ <key>remediationFactor</key>
<val>3.2</val>
</prop>
<prop>
- <key>function</key>
+ <key>remediationFunction</key>
<txt>linear</txt>
</prop>
</chc>
</chc>
-</sqale> \ No newline at end of file
+</sqale>
diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_with_linear_with_offset.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_with_linear_with_offset.xml
new file mode 100644
index 00000000000..768b43b8242
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest/shouldImportXML_with_linear_with_offset.xml
@@ -0,0 +1,30 @@
+<sqale>
+ <chc>
+ <key>USABILITY</key>
+ <name>Usability</name>
+ <desc>Estimate usability</desc>
+ </chc>
+ <chc>
+ <key>EFFICIENCY</key>
+ <name>Efficiency</name>
+
+ <chc>
+ <rule-repo>checkstyle</rule-repo>
+ <rule-key>Regexp</rule-key>
+ <prop>
+ <key>remediationFactor</key>
+ <val>3.2</val>
+ </prop>
+ <prop>
+ <key>remediationFunction</key>
+ <txt>linear</txt>
+ </prop>
+ <prop>
+ <key>offset</key>
+ <val>1.0</val>
+ <txt>h</txt>
+ </prop>
+ </chc>
+ </chc>
+
+</sqale>