From ce4052cc01ebf601332266f06b520d74d4566ce6 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Mon, 2 Dec 2013 14:01:04 +0100 Subject: [PATCH] Verify that checks do not set effort to fix on constant_issue requirement --- .../TechnicalDebtCalculator.java | 4 +++ .../TechnicalDebtCalculatorTest.java | 30 +++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculator.java b/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculator.java index 16e12f74d1d..ded5a20aa01 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculator.java +++ b/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculator.java @@ -25,6 +25,7 @@ import org.sonar.api.issue.Issue; import org.sonar.api.issue.internal.WorkDayDuration; import org.sonar.api.technicaldebt.batch.Requirement; import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; +import org.sonar.api.technicaldebt.batch.internal.DefaultRequirement; import org.sonar.api.utils.WorkUnit; import org.sonar.core.technicaldebt.TechnicalDebtConverter; @@ -44,6 +45,9 @@ public class TechnicalDebtCalculator implements BatchExtension { public WorkDayDuration calculTechnicalDebt(Issue issue) { Requirement requirement = model.requirementsByRule(issue.ruleKey()); if (requirement != null) { + if (requirement.function().equals(DefaultRequirement.CONSTANT_ISSUE) && issue.effortToFix() != null) { + throw new IllegalArgumentException("The implementation of rule '"+ issue.ruleKey() +"' defines an effort to fix whereas its requirement is set to 'constant/issue' - which is not compatible."); + } return converter.fromMinutes(calculTechnicalDebt(requirement, issue)); } return null; diff --git a/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculatorTest.java b/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculatorTest.java index 252d127504b..b4b5f55bfff 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculatorTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculatorTest.java @@ -33,6 +33,7 @@ import org.sonar.api.utils.WorkUnit; import org.sonar.core.technicaldebt.TechnicalDebtConverter; import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.Fail.fail; import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) @@ -63,6 +64,7 @@ public class TechnicalDebtCalculatorTest { DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(ruleKey); DefaultRequirement requirement = mock(DefaultRequirement.class); + Mockito.when(requirement.function()).thenReturn("constant_issue"); Mockito.when(requirement.factor()).thenReturn(tenMinutes); Mockito.when(requirement.offset()).thenReturn(fiveMinutes); when(model.requirementsByRule(ruleKey)).thenReturn(requirement); @@ -78,6 +80,7 @@ public class TechnicalDebtCalculatorTest { DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(ruleKey).setEffortToFix(2d); DefaultRequirement requirement = mock(DefaultRequirement.class); + Mockito.when(requirement.function()).thenReturn("linear_offset"); Mockito.when(requirement.factor()).thenReturn(tenMinutes); Mockito.when(requirement.offset()).thenReturn(fiveMinutes); when(model.requirementsByRule(ruleKey)).thenReturn(requirement); @@ -93,6 +96,7 @@ public class TechnicalDebtCalculatorTest { DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(ruleKey).setEffortToFix(2d); DefaultRequirement requirement = mock(DefaultRequirement.class); + Mockito.when(requirement.function()).thenReturn("linear"); Mockito.when(requirement.factor()).thenReturn(tenMinutes); Mockito.when(requirement.offset()).thenReturn(null); when(model.requirementsByRule(ruleKey)).thenReturn(requirement); @@ -105,16 +109,17 @@ public class TechnicalDebtCalculatorTest { @Test public void calcul_technical_debt_with_no_factor() throws Exception { RuleKey ruleKey = RuleKey.of("squid", "AvoidCycle"); - DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(ruleKey).setEffortToFix(2d); + DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(ruleKey); DefaultRequirement requirement = mock(DefaultRequirement.class); + Mockito.when(requirement.function()).thenReturn("constant_issue"); Mockito.when(requirement.factor()).thenReturn(null); Mockito.when(requirement.offset()).thenReturn(fiveMinutes); when(model.requirementsByRule(ruleKey)).thenReturn(requirement); remediationCostCalculator.calculTechnicalDebt(issue); - verify(converter).fromMinutes(0l * 2 + 5l); + verify(converter).fromMinutes(0l + 5l); } @Test @@ -127,5 +132,26 @@ public class TechnicalDebtCalculatorTest { verify(converter, never()).fromMinutes(anyLong()); } + @Test + public void fail_to_calcul_technical_debt_on_constant_issue_function_with_effort_to_fix() throws Exception { + RuleKey ruleKey = RuleKey.of("squid", "AvoidCycle"); + DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(ruleKey).setEffortToFix(2d); + + DefaultRequirement requirement = mock(DefaultRequirement.class); + Mockito.when(requirement.function()).thenReturn("constant_issue"); + Mockito.when(requirement.factor()).thenReturn(null); + Mockito.when(requirement.offset()).thenReturn(fiveMinutes); + when(model.requirementsByRule(ruleKey)).thenReturn(requirement); + + try { + remediationCostCalculator.calculTechnicalDebt(issue); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class) + .hasMessage("The implementation of rule 'squid:AvoidCycle' defines an effort to fix whereas its requirement is set to 'constant/issue' - which is not compatible."); + } + verifyZeroInteractions(converter); + } + } -- 2.39.5