]> source.dussan.org Git - sonarqube.git/blob
272fc1bd249fb351036f5e224979f8ddab682d07
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2019 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 package org.sonar.ce.task.projectanalysis.issue;
21
22 import java.util.Date;
23 import java.util.Random;
24 import org.junit.Test;
25 import org.sonar.api.rules.RuleType;
26 import org.sonar.api.utils.Duration;
27 import org.sonar.ce.task.projectanalysis.component.Component;
28 import org.sonar.ce.task.projectanalysis.component.ReportComponent;
29 import org.sonar.ce.task.projectanalysis.measure.Measure;
30 import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
31 import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
32 import org.sonar.ce.task.projectanalysis.period.Period;
33 import org.sonar.ce.task.projectanalysis.period.PeriodHolderRule;
34 import org.sonar.core.issue.DefaultIssue;
35
36 import static org.assertj.core.api.Assertions.assertThat;
37 import static org.assertj.guava.api.Assertions.assertThat;
38 import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
39 import static org.sonar.api.measures.CoreMetrics.NEW_RELIABILITY_REMEDIATION_EFFORT;
40 import static org.sonar.api.measures.CoreMetrics.NEW_RELIABILITY_REMEDIATION_EFFORT_KEY;
41 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_REMEDIATION_EFFORT;
42 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_REMEDIATION_EFFORT_KEY;
43 import static org.sonar.api.measures.CoreMetrics.NEW_TECHNICAL_DEBT;
44 import static org.sonar.api.measures.CoreMetrics.NEW_TECHNICAL_DEBT_KEY;
45 import static org.sonar.api.rules.RuleType.BUG;
46 import static org.sonar.api.rules.RuleType.CODE_SMELL;
47 import static org.sonar.api.rules.RuleType.VULNERABILITY;
48 import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD_MODE_PREVIOUS_VERSION;
49
50 public class NewEffortAggregatorTest {
51
52   private static final Period PERIOD = new Period(LEAK_PERIOD_MODE_PREVIOUS_VERSION, null, 1_500_000_000L, "U1");
53   private static final long[] OLD_ISSUES_DATES = new long[] {
54     PERIOD.getSnapshotDate(),
55     PERIOD.getSnapshotDate() - 1,
56     PERIOD.getSnapshotDate() - 1_200_000L,
57   };
58
59   private static final Component FILE = ReportComponent.builder(Component.Type.FILE, 1).setUuid("FILE").build();
60   private static final Component PROJECT = ReportComponent.builder(Component.Type.PROJECT, 2).addChildren(FILE).build();
61
62   @org.junit.Rule
63   public PeriodHolderRule periodsHolder = new PeriodHolderRule();
64   @org.junit.Rule
65   public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
66     .add(NEW_TECHNICAL_DEBT)
67     .add(NEW_RELIABILITY_REMEDIATION_EFFORT)
68     .add(NEW_SECURITY_REMEDIATION_EFFORT);
69   @org.junit.Rule
70   public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create();
71
72   private final Random random = new Random();
73   private NewEffortAggregator underTest = new NewEffortAggregator(periodsHolder, metricRepository, measureRepository);
74
75   @Test
76   public void sum_new_maintainability_effort_of_issues() {
77     periodsHolder.setPeriod(PERIOD);
78     DefaultIssue unresolved1 = newCodeSmellIssue(10L);
79     DefaultIssue old1 = oldCodeSmellIssue(100L);
80     DefaultIssue unresolved2 = newCodeSmellIssue(30L);
81     DefaultIssue old2 = oldCodeSmellIssue(300L);
82     DefaultIssue unresolvedWithoutDebt = newCodeSmellIssueWithoutEffort();
83     DefaultIssue resolved = newCodeSmellIssue(50L).setResolution(RESOLUTION_FIXED);
84
85     underTest.beforeComponent(FILE);
86     underTest.onIssue(FILE, unresolved1);
87     underTest.onIssue(FILE, old1);
88     underTest.onIssue(FILE, unresolved2);
89     underTest.onIssue(FILE, old2);
90     underTest.onIssue(FILE, unresolvedWithoutDebt);
91     underTest.onIssue(FILE, resolved);
92     underTest.afterComponent(FILE);
93
94     assertVariation(FILE, NEW_TECHNICAL_DEBT_KEY, 10 + 30);
95   }
96
97   @Test
98   public void new_maintainability_effort_is_only_computed_using_code_smell_issues() {
99     periodsHolder.setPeriod(PERIOD);
100     DefaultIssue codeSmellIssue = newCodeSmellIssue(10);
101     DefaultIssue oldSmellIssue = oldCodeSmellIssue(100);
102     // Issues of type BUG and VULNERABILITY should be ignored
103     DefaultIssue bugIssue = newBugIssue(15);
104     DefaultIssue oldBugIssue = oldBugIssue(150);
105     DefaultIssue vulnerabilityIssue = newVulnerabilityIssue(12);
106     DefaultIssue oldVulnerabilityIssue = oldVulnerabilityIssue(120);
107
108     underTest.beforeComponent(FILE);
109     underTest.onIssue(FILE, codeSmellIssue);
110     underTest.onIssue(FILE, oldSmellIssue);
111     underTest.onIssue(FILE, bugIssue);
112     underTest.onIssue(FILE, oldBugIssue);
113     underTest.onIssue(FILE, vulnerabilityIssue);
114     underTest.onIssue(FILE, oldVulnerabilityIssue);
115     underTest.afterComponent(FILE);
116
117     // Only effort of CODE SMELL issue is used
118     assertVariation(FILE, NEW_TECHNICAL_DEBT_KEY, 10);
119   }
120
121   @Test
122   public void sum_new_reliability_effort_of_issues() {
123     periodsHolder.setPeriod(PERIOD);
124     DefaultIssue unresolved1 = newBugIssue(10L);
125     DefaultIssue old1 = oldBugIssue(100L);
126     DefaultIssue unresolved2 = newBugIssue(30L);
127
128     DefaultIssue old2 = oldBugIssue(300L);
129     DefaultIssue unresolvedWithoutDebt = newBugIssueWithoutEffort();
130     DefaultIssue resolved = newBugIssue(50L).setResolution(RESOLUTION_FIXED);
131
132     underTest.beforeComponent(FILE);
133     underTest.onIssue(FILE, unresolved1);
134     underTest.onIssue(FILE, old1);
135     underTest.onIssue(FILE, unresolved2);
136     underTest.onIssue(FILE, old2);
137     underTest.onIssue(FILE, unresolvedWithoutDebt);
138     underTest.onIssue(FILE, resolved);
139     underTest.afterComponent(FILE);
140
141     assertVariation(FILE, NEW_RELIABILITY_REMEDIATION_EFFORT_KEY, 10 + 30);
142   }
143
144   @Test
145   public void new_reliability_effort_is_only_computed_using_bug_issues() {
146     periodsHolder.setPeriod(PERIOD);
147     DefaultIssue bugIssue = newBugIssue(15);
148     DefaultIssue oldBugIssue = oldBugIssue(150);
149     // Issues of type CODE SMELL and VULNERABILITY should be ignored
150     DefaultIssue codeSmellIssue = newCodeSmellIssue(10);
151     DefaultIssue oldCodeSmellIssue = oldCodeSmellIssue(100);
152     DefaultIssue vulnerabilityIssue = newVulnerabilityIssue(12);
153     DefaultIssue oldVulnerabilityIssue = oldVulnerabilityIssue(120);
154
155     underTest.beforeComponent(FILE);
156     underTest.onIssue(FILE, bugIssue);
157     underTest.onIssue(FILE, oldBugIssue);
158     underTest.onIssue(FILE, codeSmellIssue);
159     underTest.onIssue(FILE, oldCodeSmellIssue);
160     underTest.onIssue(FILE, vulnerabilityIssue);
161     underTest.onIssue(FILE, oldVulnerabilityIssue);
162     underTest.afterComponent(FILE);
163
164     // Only effort of BUG issue is used
165     assertVariation(FILE, NEW_RELIABILITY_REMEDIATION_EFFORT_KEY, 15);
166   }
167
168   @Test
169   public void sum_new_vulnerability_effort_of_issues() {
170     periodsHolder.setPeriod(PERIOD);
171     DefaultIssue unresolved1 = newVulnerabilityIssue(10L);
172     DefaultIssue old1 = oldVulnerabilityIssue(100L);
173     DefaultIssue unresolved2 = newVulnerabilityIssue(30L);
174     DefaultIssue old2 = oldVulnerabilityIssue(300L);
175     DefaultIssue unresolvedWithoutDebt = newVulnerabilityIssueWithoutEffort();
176     DefaultIssue resolved = newVulnerabilityIssue(50L).setResolution(RESOLUTION_FIXED);
177     DefaultIssue oldResolved = oldVulnerabilityIssue(500L).setResolution(RESOLUTION_FIXED);
178
179     underTest.beforeComponent(FILE);
180     underTest.onIssue(FILE, unresolved1);
181     underTest.onIssue(FILE, old1);
182     underTest.onIssue(FILE, unresolved2);
183     underTest.onIssue(FILE, old2);
184     underTest.onIssue(FILE, unresolvedWithoutDebt);
185     underTest.onIssue(FILE, resolved);
186     underTest.onIssue(FILE, oldResolved);
187     underTest.afterComponent(FILE);
188
189     assertVariation(FILE, NEW_SECURITY_REMEDIATION_EFFORT_KEY, 10 + 30);
190   }
191
192   @Test
193   public void new_security_effort_is_only_computed_using_vulnerability_issues() {
194     periodsHolder.setPeriod(PERIOD);
195     DefaultIssue vulnerabilityIssue = newVulnerabilityIssue(12);
196     DefaultIssue oldVulnerabilityIssue = oldVulnerabilityIssue(120);
197     // Issues of type CODE SMELL and BUG should be ignored
198     DefaultIssue codeSmellIssue = newCodeSmellIssue(10);
199     DefaultIssue oldCodeSmellIssue = oldCodeSmellIssue(100);
200     DefaultIssue bugIssue = newBugIssue(15);
201     DefaultIssue oldBugIssue = oldBugIssue(150);
202
203     underTest.beforeComponent(FILE);
204     underTest.onIssue(FILE, codeSmellIssue);
205     underTest.onIssue(FILE, oldCodeSmellIssue);
206     underTest.onIssue(FILE, bugIssue);
207     underTest.onIssue(FILE, oldBugIssue);
208     underTest.onIssue(FILE, vulnerabilityIssue);
209     underTest.onIssue(FILE, oldVulnerabilityIssue);
210     underTest.afterComponent(FILE);
211
212     // Only effort of VULNERABILITY issue is used
213     assertVariation(FILE, NEW_SECURITY_REMEDIATION_EFFORT_KEY, 12);
214   }
215
216   @Test
217   public void aggregate_new_characteristic_measures_of_children() {
218     periodsHolder.setPeriod(PERIOD);
219
220     DefaultIssue codeSmellIssue = newCodeSmellIssue(10);
221     DefaultIssue oldCodeSmellIssue = oldCodeSmellIssue(100);
222     DefaultIssue bugIssue = newBugIssue(8);
223     DefaultIssue oldBugIssue = oldBugIssue(80);
224     DefaultIssue vulnerabilityIssue = newVulnerabilityIssue(12);
225     DefaultIssue oldVulnerabilityIssue = oldVulnerabilityIssue(120);
226
227     DefaultIssue codeSmellProjectIssue = newCodeSmellIssue(30);
228     DefaultIssue oldCodeSmellProjectIssue = oldCodeSmellIssue(300);
229     DefaultIssue bugProjectIssue = newBugIssue(28);
230     DefaultIssue oldBugProjectIssue = oldBugIssue(280);
231     DefaultIssue vulnerabilityProjectIssue = newVulnerabilityIssue(32);
232     DefaultIssue oldVulnerabilityProjectIssue = oldVulnerabilityIssue(320);
233
234     underTest.beforeComponent(FILE);
235     underTest.onIssue(FILE, codeSmellIssue);
236     underTest.onIssue(FILE, oldCodeSmellIssue);
237     underTest.onIssue(FILE, bugIssue);
238     underTest.onIssue(FILE, oldBugIssue);
239     underTest.onIssue(FILE, vulnerabilityIssue);
240     underTest.onIssue(FILE, oldVulnerabilityIssue);
241     underTest.afterComponent(FILE);
242     underTest.beforeComponent(PROJECT);
243     underTest.onIssue(PROJECT, codeSmellProjectIssue);
244     underTest.onIssue(PROJECT, oldCodeSmellProjectIssue);
245     underTest.onIssue(PROJECT, bugProjectIssue);
246     underTest.onIssue(PROJECT, oldBugProjectIssue);
247     underTest.onIssue(PROJECT, vulnerabilityProjectIssue);
248     underTest.onIssue(PROJECT, oldVulnerabilityProjectIssue);
249     underTest.afterComponent(PROJECT);
250
251     assertVariation(PROJECT, NEW_TECHNICAL_DEBT_KEY, 10 + 30);
252     assertVariation(PROJECT, NEW_RELIABILITY_REMEDIATION_EFFORT_KEY, 8 + 28);
253     assertVariation(PROJECT, NEW_SECURITY_REMEDIATION_EFFORT_KEY, 12 + 32);
254   }
255
256   @Test
257   public void no_measures_if_no_periods() {
258     periodsHolder.setPeriod(null);
259     DefaultIssue unresolved = newCodeSmellIssue(10);
260
261     underTest.beforeComponent(FILE);
262     underTest.onIssue(FILE, unresolved);
263     underTest.afterComponent(FILE);
264
265     assertThat(measureRepository.getRawMeasures(FILE)).isEmpty();
266   }
267
268   @Test
269   public void should_have_empty_measures_if_no_issues() {
270     periodsHolder.setPeriod(PERIOD);
271
272     underTest.beforeComponent(FILE);
273     underTest.afterComponent(FILE);
274
275     assertVariation(FILE, NEW_TECHNICAL_DEBT_KEY, 0);
276     assertVariation(FILE, NEW_RELIABILITY_REMEDIATION_EFFORT_KEY, 0);
277     assertVariation(FILE, NEW_SECURITY_REMEDIATION_EFFORT_KEY, 0);
278   }
279
280   private void assertVariation(Component component, String metricKey, int variation) {
281     Measure newMeasure = measureRepository.getRawMeasure(component, metricRepository.getByKey(metricKey)).get();
282     assertThat(newMeasure.getVariation()).isEqualTo(variation);
283     assertThat(newMeasure.getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
284   }
285
286   private static DefaultIssue newCodeSmellIssue(long effort) {
287     return newCodeSmellIssueWithoutEffort()
288       .setEffort(Duration.create(effort))
289       .setType(RuleType.CODE_SMELL)
290       .setCreationDate(new Date(PERIOD.getSnapshotDate() + 10_000L));
291   }
292
293   private DefaultIssue oldCodeSmellIssue(long effort) {
294     return newCodeSmellIssueWithoutEffort()
295       .setEffort(Duration.create(effort))
296       .setType(RuleType.CODE_SMELL)
297       .setCreationDate(new Date(OLD_ISSUES_DATES[random.nextInt(OLD_ISSUES_DATES.length)]));
298   }
299
300   private static DefaultIssue newBugIssue(long effort) {
301     return newCodeSmellIssueWithoutEffort()
302       .setEffort(Duration.create(effort))
303       .setType(RuleType.BUG)
304       .setCreationDate(new Date(PERIOD.getSnapshotDate() + 10_000L));
305   }
306
307   private DefaultIssue oldBugIssue(long effort) {
308     return newCodeSmellIssueWithoutEffort()
309       .setEffort(Duration.create(effort))
310       .setType(RuleType.BUG)
311       .setCreationDate(new Date(OLD_ISSUES_DATES[random.nextInt(OLD_ISSUES_DATES.length)]));
312   }
313
314   private static DefaultIssue newVulnerabilityIssue(long effort) {
315     return newCodeSmellIssueWithoutEffort()
316       .setEffort(Duration.create(effort))
317       .setType(RuleType.VULNERABILITY)
318       .setCreationDate(new Date(PERIOD.getSnapshotDate() + 10_000L));
319   }
320
321   private DefaultIssue oldVulnerabilityIssue(long effort) {
322     return newCodeSmellIssueWithoutEffort()
323       .setEffort(Duration.create(effort))
324       .setType(RuleType.VULNERABILITY)
325       .setCreationDate(new Date(OLD_ISSUES_DATES[random.nextInt(OLD_ISSUES_DATES.length)]));
326   }
327
328   private static DefaultIssue newCodeSmellIssueWithoutEffort() {
329     return new DefaultIssue()
330       .setType(CODE_SMELL)
331       .setCreationDate(new Date(PERIOD.getSnapshotDate() + 10_000L));
332   }
333
334   private static DefaultIssue newBugIssueWithoutEffort() {
335     return new DefaultIssue().setType(BUG);
336   }
337
338   private static DefaultIssue newVulnerabilityIssueWithoutEffort() {
339     return new DefaultIssue().setType(VULNERABILITY);
340   }
341 }