Browse Source

Fix quality flaws

tags/4.3
Julien Lancelot 10 years ago
parent
commit
4a108310e1
16 changed files with 214 additions and 117 deletions
  1. 1
    1
      sonar-core/src/main/java/org/sonar/core/rule/RuleDto.java
  2. 4
    1
      sonar-plugin-api/src/main/java/org/sonar/api/server/debt/internal/DefaultDebtCharacteristic.java
  3. 19
    20
      sonar-plugin-api/src/main/java/org/sonar/api/server/debt/internal/DefaultDebtRemediationFunction.java
  4. 4
    4
      sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java
  5. 31
    25
      sonar-server/src/main/java/org/sonar/server/debt/DebtModelBackup.java
  6. 3
    2
      sonar-server/src/main/java/org/sonar/server/debt/DebtModelLookup.java
  7. 15
    4
      sonar-server/src/main/java/org/sonar/server/debt/DebtModelOperations.java
  8. 21
    10
      sonar-server/src/main/java/org/sonar/server/debt/DebtModelXMLExporter.java
  9. 13
    12
      sonar-server/src/main/java/org/sonar/server/debt/DebtRulesXMLImporter.java
  10. 14
    13
      sonar-server/src/main/java/org/sonar/server/rule/DeprecatedRulesDefinition.java
  11. 9
    9
      sonar-server/src/test/java/org/sonar/server/debt/DebtModelBackupTest.java
  12. 36
    0
      sonar-server/src/test/java/org/sonar/server/debt/DebtModelOperationsTest.java
  13. 3
    3
      sonar-server/src/test/java/org/sonar/server/debt/DebtModelXMLExporterTest.java
  14. 12
    12
      sonar-server/src/test/java/org/sonar/server/debt/DebtRulesXMLImporterTest.java
  15. 29
    1
      sonar-server/src/test/java/org/sonar/server/rule/DeprecatedRulesDefinitionTest.java
  16. 0
    0
      sonar-server/src/test/resources/org/sonar/server/debt/DebtRulesXMLImporterTest/convert_constant_per_issue_with_coefficient_by_constant_per_issue_with_offset.xml

+ 1
- 1
sonar-core/src/main/java/org/sonar/core/rule/RuleDto.java View File

@@ -315,7 +315,7 @@ public final class RuleDto {
}

public boolean hasCharacteristic(){
return ((characteristicId != null && !RuleDto.DISABLED_CHARACTERISTIC_ID.equals(characteristicId))) || (characteristicId == null && defaultCharacteristicId != null);
return (characteristicId != null && !RuleDto.DISABLED_CHARACTERISTIC_ID.equals(characteristicId)) || (characteristicId == null && defaultCharacteristicId != null);
}

@Override

+ 4
- 1
sonar-plugin-api/src/main/java/org/sonar/api/server/debt/internal/DefaultDebtCharacteristic.java View File

@@ -83,15 +83,17 @@ public class DefaultDebtCharacteristic implements DebtCharacteristic {
}

@Override
@CheckForNull
public Integer parentId() {
return parentId;
}

public DefaultDebtCharacteristic setParentId(Integer parentId) {
public DefaultDebtCharacteristic setParentId(@Nullable Integer parentId) {
this.parentId = parentId;
return this;
}

@Override
public Date createdAt() {
return createdAt;
}
@@ -101,6 +103,7 @@ public class DefaultDebtCharacteristic implements DebtCharacteristic {
return this;
}

@Override
@CheckForNull
public Date updatedAt() {
return updatedAt;

+ 19
- 20
sonar-plugin-api/src/main/java/org/sonar/api/server/debt/internal/DefaultDebtRemediationFunction.java View File

@@ -22,6 +22,7 @@ package org.sonar.api.server.debt.internal;

import com.google.common.base.Objects;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.utils.Duration;

@@ -33,12 +34,12 @@ public class DefaultDebtRemediationFunction implements DebtRemediationFunction {
private static final int HOURS_IN_DAY = 24;

private final Type type;
private final String factor;
private final String coefficient;
private final String offset;

public DefaultDebtRemediationFunction(Type type, @Nullable String factor, @Nullable String offset) {
public DefaultDebtRemediationFunction(Type type, @Nullable String coefficient, @Nullable String offset) {
this.type = type;
this.factor = sanitizeValue("coefficient", factor);
this.coefficient = sanitizeValue("coefficient", coefficient);
this.offset = sanitizeValue("offset", offset);
validate();
}
@@ -64,7 +65,7 @@ public class DefaultDebtRemediationFunction implements DebtRemediationFunction {
@Override
@CheckForNull
public String coefficient() {
return factor;
return coefficient;
}

@Override
@@ -76,17 +77,17 @@ public class DefaultDebtRemediationFunction implements DebtRemediationFunction {
private void validate() {
switch (type) {
case LINEAR:
if (this.factor == null || this.offset != null) {
if (this.coefficient == null || this.offset != null) {
throw new IllegalArgumentException(String.format("Only coefficient must be set on %s", this));
}
break;
case LINEAR_OFFSET:
if (this.factor == null || this.offset == null) {
if (this.coefficient == null || this.offset == null) {
throw new IllegalArgumentException(String.format("Both coefficient and offset are required on %s", this));
}
break;
case CONSTANT_ISSUE:
if (this.factor != null || this.offset == null) {
if (this.coefficient != null || this.offset == null) {
throw new IllegalArgumentException(String.format("Only offset must be set on %s", this));
}
break;
@@ -97,26 +98,24 @@ public class DefaultDebtRemediationFunction implements DebtRemediationFunction {

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
DefaultDebtRemediationFunction that = (DefaultDebtRemediationFunction) o;
if (factor != null ? !factor.equals(that.factor) : that.factor != null) {
if (!(o instanceof DefaultDebtRemediationFunction)) {
return false;
}
if (offset != null ? !offset.equals(that.offset) : that.offset != null) {
return false;
if (this == o) {
return true;
}
return type == that.type;
DefaultDebtRemediationFunction other = (DefaultDebtRemediationFunction) o;
return new EqualsBuilder()
.append(coefficient, other.coefficient())
.append(offset, other.offset())
.append(type, other.type())
.isEquals();
}

@Override
public int hashCode() {
int result = type.hashCode();
result = 31 * result + (factor != null ? factor.hashCode() : 0);
result = 31 * result + (coefficient != null ? coefficient.hashCode() : 0);
result = 31 * result + (offset != null ? offset.hashCode() : 0);
return result;
}
@@ -125,7 +124,7 @@ public class DefaultDebtRemediationFunction implements DebtRemediationFunction {
public String toString() {
return Objects.toStringHelper(DebtRemediationFunction.class)
.add("type", type)
.add("coefficient", factor)
.add("coefficient", coefficient)
.add("offset", offset)
.toString();
}

+ 4
- 4
sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java View File

@@ -137,10 +137,6 @@ public interface RulesDefinition extends ServerExtension {
* Default sub-characteristics of technical debt model. See http://www.sqale.org
*/
final class SubCharacteristics {
private SubCharacteristics() {
// only constants
}

/**
* Related to characteristic REUSABILITY
*/
@@ -295,6 +291,10 @@ public interface RulesDefinition extends ServerExtension {
* Related to characteristic TESTABILITY
*/
public static final String UNIT_TESTABILITY = "UNIT_TESTABILITY";

private SubCharacteristics() {
// only constants
}
}

/**

+ 31
- 25
sonar-server/src/main/java/org/sonar/server/debt/DebtModelBackup.java View File

@@ -112,9 +112,11 @@ public class DebtModelBackup implements ServerComponent {

List<RuleDebt> rules = newArrayList();
for (RuleDto rule : ruleDao.selectEnablesAndNonManual(session)) {
if ((languageKey == null || languageKey.equals(rule.getLanguage())) && rule.hasCharacteristic()) {
Integer characteristicId = rule.getCharacteristicId() != null ? rule.getCharacteristicId() : rule.getDefaultCharacteristicId();
rules.add(toRuleDebt(rule, debtModel.characteristicById(characteristicId).key()));
if ((languageKey == null || languageKey.equals(rule.getLanguage()))) {
Integer effectiveCharacteristicId = rule.getCharacteristicId() != null ? rule.getCharacteristicId() : rule.getDefaultCharacteristicId();
if (effectiveCharacteristicId != null && !RuleDto.DISABLED_CHARACTERISTIC_ID.equals(effectiveCharacteristicId)) {
rules.add(toRuleDebt(rule, debtModel.characteristicById(effectiveCharacteristicId).key()));
}
}
}
return debtModelXMLExporter.export(debtModel, rules);
@@ -151,8 +153,8 @@ public class DebtModelBackup implements ServerComponent {
try {
List<RuleDto> rules = newArrayList(Iterables.filter(ruleDao.selectEnablesAndNonManual(session), new Predicate<RuleDto>() {
@Override
public boolean apply(RuleDto input) {
return languageKey.equals(input.getLanguage());
public boolean apply(@Nullable RuleDto input) {
return input != null && languageKey.equals(input.getLanguage());
}
}));
restoreProvidedModel(rules, updateDate, session);
@@ -201,8 +203,8 @@ public class DebtModelBackup implements ServerComponent {
List<CharacteristicDto> characteristicDtos = dao.selectEnabledCharacteristics(session);
List<RuleDto> rules = newArrayList(Iterables.filter(ruleDao.selectEnablesAndNonManual(session), new Predicate<RuleDto>() {
@Override
public boolean apply(RuleDto input) {
return languageKey.equals(input.getLanguage());
public boolean apply(@Nullable RuleDto input) {
return input != null && languageKey.equals(input.getLanguage());
}
}));
restoreRules(characteristicDtos, rules, rulesXMLImporter.importXML(xml, validationMessages), validationMessages, updateDate, session);
@@ -227,10 +229,10 @@ public class DebtModelBackup implements ServerComponent {
} else {
boolean isSameCharacteristic = characteristicDto.getId().equals(rule.getDefaultCharacteristicId());
boolean isSameFunction = isSameRemediationFunction(ruleDebt, rule);
rule.setCharacteristicId((!isSameCharacteristic ? characteristicDto.getId() : null));
rule.setRemediationFunction((!isSameFunction ? ruleDebt.function().name() : null));
rule.setRemediationCoefficient((!isSameFunction ? ruleDebt.factor() : null));
rule.setRemediationOffset((!isSameFunction ? ruleDebt.offset() : null));
rule.setCharacteristicId(!isSameCharacteristic ? characteristicDto.getId() : null);
rule.setRemediationFunction(!isSameFunction ? ruleDebt.function().name() : null);
rule.setRemediationCoefficient(!isSameFunction ? ruleDebt.coefficient() : null);
rule.setRemediationOffset(!isSameFunction ? ruleDebt.offset() : null);
rule.setUpdatedAt(updateDate);
ruleDao.update(rule, session);
// TODO index rules in E/S
@@ -290,12 +292,12 @@ public class DebtModelBackup implements ServerComponent {
private static boolean isSameRemediationFunction(RuleDebt ruleDebt, RuleDto rule) {
return new EqualsBuilder()
.append(ruleDebt.function().name(), rule.getDefaultRemediationFunction())
.append(ruleDebt.factor(), rule.getDefaultRemediationCoefficient())
.append(ruleDebt.coefficient(), rule.getDefaultRemediationCoefficient())
.append(ruleDebt.offset(), rule.getDefaultRemediationOffset())
.isEquals();
}

private void disabledRuleDebt(RuleDto rule, Date updateDate, SqlSession session){
private void disabledRuleDebt(RuleDto rule, Date updateDate, SqlSession session) {
rule.setCharacteristicId(rule.getDefaultCharacteristicId() != null ? RuleDto.DISABLED_CHARACTERISTIC_ID : null);
rule.setRemediationFunction(null);
rule.setRemediationCoefficient(null);
@@ -321,8 +323,8 @@ public class DebtModelBackup implements ServerComponent {
}
return Iterables.find(ruleDebts, new Predicate<RuleDebt>() {
@Override
public boolean apply(RuleDebt input) {
return rule.getRepositoryKey().equals(input.ruleKey().repository()) && rule.getRuleKey().equals(input.ruleKey().rule());
public boolean apply(@Nullable RuleDebt input) {
return input != null && rule.getRepositoryKey().equals(input.ruleKey().repository()) && rule.getRuleKey().equals(input.ruleKey().rule());
}
}, null);
}
@@ -331,8 +333,8 @@ public class DebtModelBackup implements ServerComponent {
private static CharacteristicDto characteristicByKey(final String key, List<CharacteristicDto> characteristicDtos) {
return Iterables.find(characteristicDtos, new Predicate<CharacteristicDto>() {
@Override
public boolean apply(CharacteristicDto input) {
return key.equals(input.getKey());
public boolean apply(@Nullable CharacteristicDto input) {
return input != null && key.equals(input.getKey());
}
}, null);
}
@@ -340,21 +342,25 @@ public class DebtModelBackup implements ServerComponent {
private static List<CharacteristicDto> subCharacteristics(final Integer parentId, List<CharacteristicDto> allCharacteristics) {
return newArrayList(Iterables.filter(allCharacteristics, new Predicate<CharacteristicDto>() {
@Override
public boolean apply(CharacteristicDto input) {
return parentId.equals(input.getParentId());
public boolean apply(@Nullable CharacteristicDto input) {
return input != null && parentId.equals(input.getParentId());
}
}));
}

private static RuleDebt toRuleDebt(RuleDto rule, String characteristicKey) {
RuleDebt ruleDebt = new RuleDebt().setRuleKey(RuleKey.of(rule.getRepositoryKey(), rule.getRuleKey()));
String function = rule.getRemediationFunction() != null ? rule.getRemediationFunction() : rule.getDefaultRemediationFunction();
String factor = rule.getRemediationCoefficient() != null ? rule.getRemediationCoefficient() : rule.getDefaultRemediationCoefficient();
String offset = rule.getRemediationOffset() != null ? rule.getRemediationOffset() : rule.getDefaultRemediationOffset();
String function = rule.getRemediationFunction();
String coefficient = rule.getRemediationCoefficient();
String offset = rule.getRemediationOffset();

String effectiveFunction = function != null ? function : rule.getDefaultRemediationFunction();
String effectiveCoefficient = coefficient != null ? coefficient : rule.getDefaultRemediationCoefficient();
String effectiveOffset = offset != null ? offset : rule.getDefaultRemediationOffset();
ruleDebt.setCharacteristicKey(characteristicKey);
ruleDebt.setFunction(DebtRemediationFunction.Type.valueOf(function));
ruleDebt.setFactor(factor);
ruleDebt.setOffset(offset);
ruleDebt.setFunction(DebtRemediationFunction.Type.valueOf(effectiveFunction));
ruleDebt.setCoefficient(effectiveCoefficient);
ruleDebt.setOffset(effectiveOffset);
return ruleDebt;
}


+ 3
- 2
sonar-server/src/main/java/org/sonar/server/debt/DebtModelLookup.java View File

@@ -29,6 +29,7 @@ import org.sonar.core.technicaldebt.db.CharacteristicDao;
import org.sonar.core.technicaldebt.db.CharacteristicDto;

import javax.annotation.CheckForNull;
import javax.annotation.Nullable;

import java.util.Collection;
import java.util.List;
@@ -60,8 +61,8 @@ public class DebtModelLookup implements ServerComponent {
private static List<DebtCharacteristic> toCharacteristics(Collection<CharacteristicDto> dtos) {
return newArrayList(Iterables.transform(dtos, new Function<CharacteristicDto, DebtCharacteristic>() {
@Override
public DebtCharacteristic apply(CharacteristicDto input) {
return toCharacteristic(input);
public DebtCharacteristic apply(@Nullable CharacteristicDto input) {
return input != null ? toCharacteristic(input) : null;
}
}));
}

+ 15
- 4
sonar-server/src/main/java/org/sonar/server/debt/DebtModelOperations.java View File

@@ -130,7 +130,10 @@ public class DebtModelOperations implements ServerComponent {
SqlSession session = mybatis.openSession();
try {
final CharacteristicDto dto = findCharacteristic(characteristicId, session);
int currentOrder = dto.getOrder();
if (dto.getParentId() != null) {
throw new BadRequestException("Sub characteristics can not be moved.");
}
int currentOrder = getOrder(dto);
CharacteristicDto dtoToSwitchOrderWith = findCharacteristicToSwitchWith(dto, moveUpOrDown, session);

// Do nothing when characteristic is already to the good location
@@ -138,7 +141,7 @@ public class DebtModelOperations implements ServerComponent {
return toCharacteristic(dto);
}

int nextOrder = dtoToSwitchOrderWith.getOrder();
int nextOrder = getOrder(dtoToSwitchOrderWith);
dtoToSwitchOrderWith.setOrder(currentOrder);
dtoToSwitchOrderWith.setUpdatedAt(new Date(system2.now()));
dao.update(dtoToSwitchOrderWith, session);
@@ -154,14 +157,22 @@ public class DebtModelOperations implements ServerComponent {
}
}

private int getOrder(CharacteristicDto characteristicDto){
Integer order= characteristicDto.getOrder();
if (order == null) {
throw new IllegalArgumentException(String.format("The order of the characteristic '%s' should not be null", characteristicDto.getKey()));
}
return order;
}

@CheckForNull
private CharacteristicDto findCharacteristicToSwitchWith(final CharacteristicDto dto, final boolean moveUpOrDown, SqlSession session) {
// characteristics should be order by 'order'
List<CharacteristicDto> rootCharacteristics = dao.selectEnabledRootCharacteristics(session);
int currentPosition = Iterables.indexOf(rootCharacteristics, new Predicate<CharacteristicDto>() {
@Override
public boolean apply(CharacteristicDto input) {
return input.getKey().equals(dto.getKey());
public boolean apply(@Nullable CharacteristicDto input) {
return input != null && input.getKey().equals(dto.getKey());
}
});
Integer nextPosition = moveUpOrDown ? (currentPosition > 0 ? currentPosition - 1 : null) : (currentPosition < rootCharacteristics.size() - 1 ? currentPosition + 1 : null);

+ 21
- 10
sonar-server/src/main/java/org/sonar/server/debt/DebtModelXMLExporter.java View File

@@ -68,7 +68,7 @@ public class DebtModelXMLExporter implements ServerComponent {
public static final String RULE_KEY = "rule-key";

public static final String PROPERTY_FUNCTION = "remediationFunction";
public static final String PROPERTY_FACTOR = "remediationFactor";
public static final String PROPERTY_COEFFICIENT = "remediationFactor";
public static final String PROPERTY_OFFSET = "offset";

protected String export(DebtModel debtModel, List<RuleDebt> allRules) {
@@ -114,13 +114,13 @@ public class DebtModelXMLExporter implements ServerComponent {
xml.append(StringEscapeUtils.escapeXml(rule.ruleKey().rule()));
xml.append("</" + RULE_KEY + ">");

String factor = rule.factor();
String coefficient = rule.coefficient();
String offset = rule.offset();

appendProperty(PROPERTY_FUNCTION, null, rule.function().name(), xml);
if (factor != null) {
String[] values = getValues(factor);
appendProperty(PROPERTY_FACTOR, values[0], values[1], xml);
if (coefficient != null) {
String[] values = getValues(coefficient);
appendProperty(PROPERTY_COEFFICIENT, values[0], values[1], xml);
}
if (offset != null) {
String[] values = getValues(offset);
@@ -266,7 +266,7 @@ public class DebtModelXMLExporter implements ServerComponent {
private RuleKey ruleKey;
private String characteristicKey;
private DebtRemediationFunction.Type type;
private String factor;
private String coefficient;
private String offset;

public RuleKey ruleKey() {
@@ -297,12 +297,12 @@ public class DebtModelXMLExporter implements ServerComponent {
}

@CheckForNull
public String factor() {
return factor;
public String coefficient() {
return coefficient;
}

public RuleDebt setFactor(@Nullable String factor) {
this.factor = factor;
public RuleDebt setCoefficient(@Nullable String coefficient) {
this.coefficient = coefficient;
return this;
}

@@ -315,6 +315,17 @@ public class DebtModelXMLExporter implements ServerComponent {
this.offset = offset;
return this;
}

@Override
public String toString() {
return "RuleDebt{" +
"ruleKey=" + ruleKey +
", characteristicKey='" + characteristicKey + '\'' +
", type=" + type +
", coefficient='" + coefficient + '\'' +
", offset='" + offset + '\'' +
'}';
}
}

}

+ 13
- 12
sonar-server/src/main/java/org/sonar/server/debt/DebtRulesXMLImporter.java View File

@@ -85,7 +85,8 @@ public class DebtRulesXMLImporter implements ServerComponent {
return new SMInputFactory(xmlFactory);
}

private void process(List<RuleDebt> ruleDebts, @Nullable String rootKey, @Nullable String parentKey, ValidationMessages validationMessages, SMInputCursor chcCursor) throws XMLStreamException {
private void process(List<RuleDebt> ruleDebts, @Nullable String rootKey, @Nullable String parentKey,
ValidationMessages validationMessages, SMInputCursor chcCursor) throws XMLStreamException {
String currentCharacteristicKey = null;
SMInputCursor cursor = chcCursor.childElementCursor();
while (cursor.getNext() != null) {
@@ -159,27 +160,27 @@ public class DebtRulesXMLImporter implements ServerComponent {
Property function = properties.function();
if (function != null) {

Property factorProperty = properties.factor();
String factor = factorProperty != null ? factorProperty.toDuration() : null;
Property coefficientProperty = properties.coefficient();
String coefficient = coefficientProperty != null ? coefficientProperty.toDuration() : null;
Property offsetProperty = properties.offset();
String offset = offsetProperty != null ? offsetProperty.toDuration() : null;

return createRuleDebt(ruleKey, function.getTextValue(), factor, offset, validationMessages);
return createRuleDebt(ruleKey, function.getTextValue(), coefficient, offset, validationMessages);
}
return null;
}

@CheckForNull
private RuleDebt createRuleDebt(RuleKey ruleKey, String function, @Nullable String factor, @Nullable String offset, ValidationMessages validationMessages) {
if ("linear_threshold".equals(function) && factor != null) {
private RuleDebt createRuleDebt(RuleKey ruleKey, String function, @Nullable String coefficient, @Nullable String offset, ValidationMessages validationMessages) {
if ("linear_threshold".equals(function) && coefficient != null) {
validationMessages.addWarningText(String.format("Linear with threshold function is no longer used, remediation function of '%s' is replaced by linear.", ruleKey));
return new RuleDebt().setRuleKey(ruleKey).setFunction(DebtRemediationFunction.Type.LINEAR).setFactor(factor);
return new RuleDebt().setRuleKey(ruleKey).setFunction(DebtRemediationFunction.Type.LINEAR).setCoefficient(coefficient);
} else if ("constant_resource".equals(function)) {
validationMessages.addWarningText(String.format("Constant/file function is no longer used, technical debt definitions on '%s' are ignored.", ruleKey));
} else if (DebtRemediationFunction.Type.CONSTANT_ISSUE.name().equalsIgnoreCase(function) && factor != null && offset == null) {
return new RuleDebt().setRuleKey(ruleKey).setFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE).setOffset(factor);
} else if (DebtRemediationFunction.Type.CONSTANT_ISSUE.name().equalsIgnoreCase(function) && coefficient != null && offset == null) {
return new RuleDebt().setRuleKey(ruleKey).setFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE).setOffset(coefficient);
} else {
return new RuleDebt().setRuleKey(ruleKey).setFunction(DebtRemediationFunction.Type.valueOf(function.toUpperCase())).setFactor(factor).setOffset(offset);
return new RuleDebt().setRuleKey(ruleKey).setFunction(DebtRemediationFunction.Type.valueOf(function.toUpperCase())).setCoefficient(coefficient).setOffset(offset);
}
return null;
}
@@ -200,8 +201,8 @@ public class DebtRulesXMLImporter implements ServerComponent {
return find(PROPERTY_FUNCTION);
}

public Property factor() {
return find(PROPERTY_FACTOR);
public Property coefficient() {
return find(PROPERTY_COEFFICIENT);
}

public Property offset() {

+ 14
- 13
sonar-server/src/main/java/org/sonar/server/rule/DeprecatedRulesDefinition.java View File

@@ -29,6 +29,7 @@ import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.RuleStatus;
import org.sonar.api.rules.RuleParam;
import org.sonar.api.rules.RuleRepository;
import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.server.rule.RuleParamType;
import org.sonar.api.server.rule.RulesDefinition;
import org.sonar.api.utils.ValidationMessages;
@@ -108,22 +109,22 @@ public class DeprecatedRulesDefinition implements RulesDefinition {
}
}

private void updateRuleDebtDefinitions(NewRule newRule, String repoKey, String ruleKey, List<RuleDebt> ruleDebts){
private void updateRuleDebtDefinitions(NewRule newRule, String repoKey, String ruleKey, List<RuleDebt> ruleDebts) {
RuleDebt ruleDebt = findRequirement(ruleDebts, repoKey, ruleKey);
if (ruleDebt != null) {
newRule.setDebtSubCharacteristic(ruleDebt.characteristicKey());
switch (ruleDebt.function()) {
case LINEAR :
newRule.setDebtRemediationFunction(newRule.debtRemediationFunctions().linear(ruleDebt.factor()));
break;
case LINEAR_OFFSET:
newRule.setDebtRemediationFunction(newRule.debtRemediationFunctions().linearWithOffset(ruleDebt.factor(), ruleDebt.offset()));
break;
case CONSTANT_ISSUE:
newRule.setDebtRemediationFunction(newRule.debtRemediationFunctions().constantPerIssue(ruleDebt.offset()));
break;
default :
throw new IllegalArgumentException(String.format("The type '%s' is unknown", ruleDebt.function()));
DebtRemediationFunction.Type function = ruleDebt.function();
String coefficient = ruleDebt.coefficient();
String offset = ruleDebt.offset();
if (DebtRemediationFunction.Type.LINEAR.equals(function) && coefficient != null) {
newRule.setDebtRemediationFunction(newRule.debtRemediationFunctions().linear(coefficient));
} else if (DebtRemediationFunction.Type.CONSTANT_ISSUE.equals(function) && offset != null) {
newRule.setDebtRemediationFunction(newRule.debtRemediationFunctions().constantPerIssue(offset));
} else if (DebtRemediationFunction.Type.LINEAR_OFFSET.equals(function) && coefficient != null && offset != null) {
newRule.setDebtRemediationFunction(newRule.debtRemediationFunctions().linearWithOffset(coefficient, offset));
} else {
throw new IllegalArgumentException(String.format("Debt definition on rule '%s:%s' is invalid", repoKey, ruleKey));
}
}
}

+ 9
- 9
sonar-server/src/test/java/org/sonar/server/debt/DebtModelBackupTest.java View File

@@ -169,7 +169,7 @@ public class DebtModelBackupTest {
assertThat(rule.ruleKey().rule()).isEqualTo("UselessImportCheck");
assertThat(rule.characteristicKey()).isEqualTo("COMPILER");
assertThat(rule.function().name()).isEqualTo("LINEAR_OFFSET");
assertThat(rule.factor()).isEqualTo("2h");
assertThat(rule.coefficient()).isEqualTo("2h");
assertThat(rule.offset()).isEqualTo("15min");

rule = rules.get(1);
@@ -177,7 +177,7 @@ public class DebtModelBackupTest {
assertThat(rule.ruleKey().rule()).isEqualTo("AvoidNPE");
assertThat(rule.characteristicKey()).isEqualTo("COMPILER");
assertThat(rule.function().name()).isEqualTo("LINEAR");
assertThat(rule.factor()).isEqualTo("2h");
assertThat(rule.coefficient()).isEqualTo("2h");
assertThat(rule.offset()).isNull();
}

@@ -232,7 +232,7 @@ public class DebtModelBackupTest {
assertThat(rule.ruleKey().rule()).isEqualTo("UselessImportCheck");
assertThat(rule.characteristicKey()).isEqualTo("COMPILER");
assertThat(rule.function().name()).isEqualTo("CONSTANT_ISSUE");
assertThat(rule.factor()).isNull();
assertThat(rule.coefficient()).isNull();
assertThat(rule.offset()).isEqualTo("15min");
}

@@ -428,7 +428,7 @@ public class DebtModelBackupTest {
new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler").setParentId(1).setCreatedAt(oldDate)));

when(rulesXMLImporter.importXML(anyString(), any(ValidationMessages.class))).thenReturn(newArrayList(new RuleDebt()
.setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("COMPILER").setFunction(DebtRemediationFunction.Type.LINEAR).setFactor("2h")));
.setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("COMPILER").setFunction(DebtRemediationFunction.Type.LINEAR).setCoefficient("2h")));

when(ruleDao.selectEnablesAndNonManual(session)).thenReturn(newArrayList(
new RuleDto().setId(1).setRepositoryKey("squid").setRuleKey("UselessImportCheck")
@@ -464,7 +464,7 @@ public class DebtModelBackupTest {
new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler").setParentId(1).setCreatedAt(oldDate)));

when(rulesXMLImporter.importXML(anyString(), any(ValidationMessages.class))).thenReturn(newArrayList(new RuleDebt()
.setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("COMPILER").setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET).setFactor("12h").setOffset("11min")));
.setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("COMPILER").setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET).setCoefficient("12h").setOffset("11min")));

when(ruleDao.selectEnablesAndNonManual(session)).thenReturn(newArrayList(
new RuleDto().setId(1).setRepositoryKey("squid").setRuleKey("UselessImportCheck")
@@ -500,7 +500,7 @@ public class DebtModelBackupTest {
new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler").setParentId(1).setCreatedAt(oldDate)));

when(rulesXMLImporter.importXML(anyString(), any(ValidationMessages.class))).thenReturn(newArrayList(new RuleDebt()
.setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("COMPILER").setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET).setFactor("2h").setOffset("15min")));
.setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("COMPILER").setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET).setCoefficient("2h").setOffset("15min")));

when(ruleDao.selectEnablesAndNonManual(session)).thenReturn(newArrayList(
new RuleDto().setId(1).setRepositoryKey("squid").setRuleKey("UselessImportCheck")
@@ -598,7 +598,7 @@ public class DebtModelBackupTest {
new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler").setParentId(1).setCreatedAt(oldDate)));

when(rulesXMLImporter.importXML(anyString(), any(ValidationMessages.class))).thenReturn(newArrayList(new RuleDebt()
.setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("COMPILER").setFunction(DebtRemediationFunction.Type.LINEAR).setFactor("2h")));
.setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("COMPILER").setFunction(DebtRemediationFunction.Type.LINEAR).setCoefficient("2h")));

when(ruleDao.selectEnablesAndNonManual(session)).thenReturn(newArrayList(
new RuleDto().setId(1).setRepositoryKey("squid").setRuleKey("UselessImportCheck").setLanguage("java")
@@ -677,7 +677,7 @@ public class DebtModelBackupTest {

when(rulesXMLImporter.importXML(anyString(), any(ValidationMessages.class))).thenReturn(newArrayList(new RuleDebt()
// Linked on a default disabled characteristic -> Rule debt should be disabled
.setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("HARDWARE").setFunction(DebtRemediationFunction.Type.LINEAR).setFactor("2h")));
.setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("HARDWARE").setFunction(DebtRemediationFunction.Type.LINEAR).setCoefficient("2h")));

debtModelBackup.restoreFromXml("<xml/>", "java");

@@ -710,7 +710,7 @@ public class DebtModelBackupTest {
new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler").setParentId(1).setCreatedAt(oldDate)));

when(rulesXMLImporter.importXML(anyString(), any(ValidationMessages.class))).thenReturn(newArrayList(new RuleDebt()
.setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("COMPILER").setFunction(DebtRemediationFunction.Type.LINEAR).setFactor("2h")));
.setRuleKey(RuleKey.of("squid", "UselessImportCheck")).setCharacteristicKey("COMPILER").setFunction(DebtRemediationFunction.Type.LINEAR).setCoefficient("2h")));

when(ruleDao.selectEnablesAndNonManual(session)).thenReturn(Collections.<RuleDto>emptyList());


+ 36
- 0
sonar-server/src/test/java/org/sonar/server/debt/DebtModelOperationsTest.java View File

@@ -298,6 +298,42 @@ public class DebtModelOperationsTest {
verify(dao, never()).update(any(CharacteristicDto.class), eq(session));
}

@Test
public void fail_to_move_sub_characteristic() {
when(dao.selectById(10, session)).thenReturn(new CharacteristicDto().setId(10).setKey("MEMORY_EFFICIENCY").setParentId(1));
when(dao.selectEnabledRootCharacteristics(session)).thenReturn(newArrayList(
new CharacteristicDto().setId(10).setKey("MEMORY_EFFICIENCY").setOrder(2),
new CharacteristicDto().setId(2).setKey("PORTABILITY").setOrder(3)
));

try {
service.moveDown(10);
fail();
} catch (Exception e) {
assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("Sub characteristics can not be moved.");
}

verify(dao, never()).update(any(CharacteristicDto.class), eq(session));
}

@Test
public void fail_to_move_characteristic_with_no_order() {
when(dao.selectById(10, session)).thenReturn(new CharacteristicDto().setId(10).setKey("MEMORY_EFFICIENCY").setOrder(null));
when(dao.selectEnabledRootCharacteristics(session)).thenReturn(newArrayList(
new CharacteristicDto().setId(10).setKey("MEMORY_EFFICIENCY").setOrder(2),
new CharacteristicDto().setId(2).setKey("PORTABILITY").setOrder(3)
));

try {
service.moveDown(10);
fail();
} catch (Exception e) {
assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("The order of the characteristic 'MEMORY_EFFICIENCY' should not be null");
}

verify(dao, never()).update(any(CharacteristicDto.class), eq(session));
}

@Test
public void delete_sub_characteristic() {
BatchSession batchSession = mock(BatchSession.class);

+ 3
- 3
sonar-server/src/test/java/org/sonar/server/debt/DebtModelXMLExporterTest.java View File

@@ -25,8 +25,8 @@ import org.apache.commons.lang.SystemUtils;
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic;
import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic;
import org.sonar.test.TestUtils;

import java.io.IOException;
@@ -62,7 +62,7 @@ public class DebtModelXMLExporterTest {

List<RuleDebt> rules = newArrayList(
new RuleDebt().setRuleKey(RuleKey.of("checkstyle", "Regexp"))
.setCharacteristicKey("MEMORY_USE").setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET).setFactor("3d").setOffset("15min")
.setCharacteristicKey("MEMORY_USE").setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET).setCoefficient("3d").setOffset("15min")
);

TestUtils.assertSimilarXml(getFileContent("export_xml.xml"), xmlExporter.export(debtModel, rules));
@@ -99,7 +99,7 @@ public class DebtModelXMLExporterTest {

List<RuleDebt> rules = newArrayList(
new RuleDebt().setRuleKey(RuleKey.of("checkstyle", "Regexp"))
.setCharacteristicKey("MEMORY_USE").setFunction(DebtRemediationFunction.Type.LINEAR).setFactor("3d")
.setCharacteristicKey("MEMORY_USE").setFunction(DebtRemediationFunction.Type.LINEAR).setCoefficient("3d")
);
assertThat(xmlExporter.export(debtModel, rules)).isEqualTo(
"<sqale>" + SystemUtils.LINE_SEPARATOR +

+ 12
- 12
sonar-server/src/test/java/org/sonar/server/debt/DebtRulesXMLImporterTest.java View File

@@ -61,7 +61,7 @@ public class DebtRulesXMLImporterTest {
assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
assertThat(ruleDebt.ruleKey()).isEqualTo(RuleKey.of("checkstyle", "Regexp"));
assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.LINEAR);
assertThat(ruleDebt.factor()).isEqualTo("3h");
assertThat(ruleDebt.coefficient()).isEqualTo("3h");
assertThat(ruleDebt.offset()).isNull();
}

@@ -76,7 +76,7 @@ public class DebtRulesXMLImporterTest {
assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
assertThat(ruleDebt.ruleKey()).isEqualTo(RuleKey.of("checkstyle", "Regexp"));
assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.LINEAR);
assertThat(ruleDebt.factor()).isEqualTo("3h");
assertThat(ruleDebt.coefficient()).isEqualTo("3h");
assertThat(ruleDebt.offset()).isNull();
}

@@ -90,7 +90,7 @@ public class DebtRulesXMLImporterTest {
RuleDebt ruleDebt = results.get(0);
assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET);
assertThat(ruleDebt.factor()).isEqualTo("3h");
assertThat(ruleDebt.coefficient()).isEqualTo("3h");
assertThat(ruleDebt.offset()).isEqualTo("1min");
}

@@ -104,7 +104,7 @@ public class DebtRulesXMLImporterTest {
RuleDebt ruleDebt = results.get(0);
assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE);
assertThat(ruleDebt.factor()).isNull();
assertThat(ruleDebt.coefficient()).isNull();
assertThat(ruleDebt.offset()).isEqualTo("3d");
}

@@ -118,7 +118,7 @@ public class DebtRulesXMLImporterTest {
RuleDebt ruleDebt = results.get(0);
assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET);
assertThat(ruleDebt.factor()).isEqualTo("3d");
assertThat(ruleDebt.coefficient()).isEqualTo("3d");
assertThat(ruleDebt.offset()).isEqualTo("1d");
}

@@ -132,7 +132,7 @@ public class DebtRulesXMLImporterTest {
RuleDebt ruleDebt = results.get(0);
assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.LINEAR);
assertThat(ruleDebt.factor()).isEqualTo("3min");
assertThat(ruleDebt.coefficient()).isEqualTo("3min");
assertThat(ruleDebt.offset()).isNull();
}

@@ -147,7 +147,7 @@ public class DebtRulesXMLImporterTest {
assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
assertThat(ruleDebt.ruleKey()).isEqualTo(RuleKey.of("checkstyle", "Regexp"));
assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.LINEAR);
assertThat(ruleDebt.factor()).isEqualTo("3h");
assertThat(ruleDebt.coefficient()).isEqualTo("3h");
assertThat(ruleDebt.offset()).isNull();
}

@@ -161,15 +161,15 @@ public class DebtRulesXMLImporterTest {
RuleDebt ruleDebt = results.get(0);
assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.LINEAR);
assertThat(ruleDebt.factor()).isEqualTo("3h");
assertThat(ruleDebt.coefficient()).isEqualTo("3h");
assertThat(ruleDebt.offset()).isNull();

assertThat(validationMessages.getWarnings()).isNotEmpty();
}

@Test
public void convert_constant_per_issue_with_factor_by_constant_by_issue_with_offset() {
String xml = getFileContent("convert_constant_per_issue_with_factor_by_constant_by_issue_with_offset.xml");
public void convert_constant_per_issue_with_coefficient_by_constant_per_issue_with_offset() {
String xml = getFileContent("convert_constant_per_issue_with_coefficient_by_constant_per_issue_with_offset.xml");

List<RuleDebt> results = importer.importXML(xml, validationMessages);
assertThat(results).hasSize(1);
@@ -177,7 +177,7 @@ public class DebtRulesXMLImporterTest {
RuleDebt ruleDebt = results.get(0);
assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE);
assertThat(ruleDebt.factor()).isNull();
assertThat(ruleDebt.coefficient()).isNull();
assertThat(ruleDebt.offset()).isEqualTo("3h");
}

@@ -212,7 +212,7 @@ public class DebtRulesXMLImporterTest {
assertThat(ruleDebt.characteristicKey()).isEqualTo("MEMORY_EFFICIENCY");
assertThat(ruleDebt.ruleKey()).isEqualTo(RuleKey.of("checkstyle", "Regexp"));
assertThat(ruleDebt.function()).isEqualTo(DebtRemediationFunction.Type.LINEAR);
assertThat(ruleDebt.factor()).isEqualTo("3h");
assertThat(ruleDebt.coefficient()).isEqualTo("3h");
assertThat(ruleDebt.offset()).isNull();
}


+ 29
- 1
sonar-server/src/test/java/org/sonar/server/rule/DeprecatedRulesDefinitionTest.java View File

@@ -43,6 +43,7 @@ import java.util.List;

import static com.google.common.collect.Lists.newArrayList;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.assertions.Fail.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
@@ -162,7 +163,7 @@ public class DeprecatedRulesDefinitionTest {
.setCharacteristicKey("MEMORY_EFFICIENCY")
.setRuleKey(RuleKey.of("checkstyle", "ConstantName"))
.setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET)
.setFactor("1d")
.setCoefficient("1d")
.setOffset("10min")
);

@@ -186,4 +187,31 @@ public class DeprecatedRulesDefinitionTest {
assertThat(rule.debtRemediationFunction().offset()).isEqualTo("10min");
}

@Test
public void fail_on_invalid_rule_debt() throws Exception {
RulesDefinition.Context context = new RulesDefinition.Context();

List<DebtModelXMLExporter.RuleDebt> ruleDebts = newArrayList(
new DebtModelXMLExporter.RuleDebt()
.setCharacteristicKey("MEMORY_EFFICIENCY")
.setRuleKey(RuleKey.of("checkstyle", "ConstantName"))
.setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET)
.setCoefficient("1d")
);

Reader javaModelReader = mock(Reader.class);
when(debtModelRepository.createReaderForXMLFile("java")).thenReturn(javaModelReader);
when(debtModelRepository.getContributingPluginList()).thenReturn(newArrayList("java"));
when(importer.importXML(eq(javaModelReader), any(ValidationMessages.class))).thenReturn(ruleDebts);

try {
new DeprecatedRulesDefinition(i18n, new RuleRepository[]{new CheckstyleRules()}, debtModelRepository, importer).define(context);
fail();
} catch (Exception e) {
assertThat(e).isInstanceOf(IllegalArgumentException.class);
}

assertThat(context.repositories()).isEmpty();
}

}

sonar-server/src/test/resources/org/sonar/server/debt/DebtRulesXMLImporterTest/convert_constant_per_issue_with_factor_by_constant_by_issue_with_offset.xml → sonar-server/src/test/resources/org/sonar/server/debt/DebtRulesXMLImporterTest/convert_constant_per_issue_with_coefficient_by_constant_per_issue_with_offset.xml View File


Loading…
Cancel
Save