]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5059 New technical debt can sometime be negative
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Fri, 14 Feb 2014 13:11:07 +0000 (14:11 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Fri, 14 Feb 2014 13:11:17 +0000 (14:11 +0100)
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/NewTechnicalDebtDecoratorTest.java
sonar-batch/src/main/java/org/sonar/batch/debt/IssueChangelogDebtCalculator.java

index d56a47f4aad6a102b4377ac063abec7cbdb95c10..c934f0c2c004d1612585efd0400862d0354ce385 100644 (file)
@@ -329,6 +329,25 @@ public class NewTechnicalDebtDecoratorTest {
     verify(context, never()).saveMeasure(argThat(new IsMeasure(CoreMetrics.NEW_TECHNICAL_DEBT)));
   }
 
+  /**
+   * SONAR-5059
+   */
+  @Test
+  public void not_return_negative_debt() {
+    Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setTechnicalDebt(oneDaysDebt).setChanges(
+      newArrayList(
+        // changelog created at is null because it has just been created on the current analysis
+        new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(twoDaysDebt), fromWorkDayDuration(oneDaysDebt)).setCreationDate(null)
+      )
+    );
+    when(issuable.issues()).thenReturn(newArrayList(issue));
+
+    decorator.decorate(resource, context);
+
+    // remember : period1 is 5daysAgo, period2 is 10daysAgo
+    verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 0.0)));
+  }
+
   private Long fromWorkDayDuration(WorkDuration workDayDuration) {
     return workDayDuration.toLong();
   }
index d8d998910787a3da55ae31c6101e003d18002427..e71edb177fc7c878f5b80e6a725b471e0b92aa66 100644 (file)
@@ -33,6 +33,7 @@ import org.sonar.core.issue.IssueUpdater;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
+
 import java.util.*;
 
 import static com.google.common.collect.Lists.newArrayList;
@@ -62,19 +63,29 @@ public class IssueChangelogDebtCalculator implements BatchComponent {
     for (Iterator<FieldDiffs> iterator = changelog.iterator(); iterator.hasNext(); ) {
       FieldDiffs diff = iterator.next();
       Date date = diff.creationDate();
+      WorkDuration newValue = newValue(diff);
+      WorkDuration oldValue = oldValue(diff);
       if (isLesserOrEqual(date, periodDate)) {
         // return new value from the change that is just before the period date
-        return currentTechnicalDebtValue.subtract(newValue(diff));
+        return subtractNeverNegative(currentTechnicalDebtValue, newValue);
       }
       if (!iterator.hasNext()) {
         // return old value from the change that is just after the period date when there's no more element in changelog
-        return currentTechnicalDebtValue.subtract(oldValue(diff));
+        return subtractNeverNegative(currentTechnicalDebtValue, oldValue);
       }
     }
     // Return null when no changelog
     return null;
   }
 
+  private WorkDuration subtractNeverNegative(WorkDuration workDuration, WorkDuration toSubtractWith){
+    WorkDuration result = workDuration.subtract(toSubtractWith);
+    if (result.toSeconds() > 0) {
+      return result;
+    }
+    return workDurationFactory.createFromWorkingLong(0L);
+  }
+
   private List<FieldDiffs> technicalDebtHistory(Issue issue) {
     List<FieldDiffs> technicalDebtChangelog = changesOnField(((DefaultIssue) issue).changes());
     if (!technicalDebtChangelog.isEmpty()) {