3 * Copyright (C) 2009-2019 SonarSource SA
4 * mailto:info AT sonarsource DOT com
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.
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.
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.
20 package org.sonar.ce.task.projectanalysis.qualitymodel;
22 import java.util.Arrays;
23 import java.util.Date;
24 import org.junit.Rule;
25 import org.junit.Test;
26 import org.sonar.api.rules.RuleType;
27 import org.sonar.api.utils.Duration;
28 import org.sonar.ce.task.projectanalysis.component.Component;
29 import org.sonar.ce.task.projectanalysis.component.FileAttributes;
30 import org.sonar.ce.task.projectanalysis.component.ReportComponent;
31 import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
32 import org.sonar.ce.task.projectanalysis.component.VisitorsCrawler;
33 import org.sonar.ce.task.projectanalysis.issue.ComponentIssuesRepositoryRule;
34 import org.sonar.ce.task.projectanalysis.issue.FillComponentIssuesVisitorRule;
35 import org.sonar.ce.task.projectanalysis.measure.MeasureAssert;
36 import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
37 import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
38 import org.sonar.ce.task.projectanalysis.period.Period;
39 import org.sonar.ce.task.projectanalysis.period.PeriodHolderRule;
40 import org.sonar.core.issue.DefaultIssue;
41 import org.sonar.core.util.Uuids;
42 import org.sonar.server.measure.Rating;
44 import static org.assertj.core.api.Assertions.assertThat;
45 import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
46 import static org.sonar.api.measures.CoreMetrics.NEW_RELIABILITY_RATING;
47 import static org.sonar.api.measures.CoreMetrics.NEW_RELIABILITY_RATING_KEY;
48 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_RATING;
49 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_RATING_KEY;
50 import static org.sonar.api.rule.Severity.BLOCKER;
51 import static org.sonar.api.rule.Severity.CRITICAL;
52 import static org.sonar.api.rule.Severity.INFO;
53 import static org.sonar.api.rule.Severity.MAJOR;
54 import static org.sonar.api.rule.Severity.MINOR;
55 import static org.sonar.api.rules.RuleType.BUG;
56 import static org.sonar.api.rules.RuleType.CODE_SMELL;
57 import static org.sonar.api.rules.RuleType.VULNERABILITY;
58 import static org.sonar.ce.task.projectanalysis.component.Component.Type.DIRECTORY;
59 import static org.sonar.ce.task.projectanalysis.component.Component.Type.FILE;
60 import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT;
61 import static org.sonar.ce.task.projectanalysis.component.ReportComponent.builder;
62 import static org.sonar.server.measure.Rating.A;
63 import static org.sonar.server.measure.Rating.B;
64 import static org.sonar.server.measure.Rating.C;
65 import static org.sonar.server.measure.Rating.D;
66 import static org.sonar.server.measure.Rating.E;
68 public class NewReliabilityAndSecurityRatingMeasuresVisitorTest {
70 private static final long LEAK_PERIOD_SNAPSHOT_IN_MILLISEC = 12323l;
71 private static final Date DEFAULT_ISSUE_CREATION_DATE = new Date(1000l);
72 private static final Date BEFORE_LEAK_PERIOD_DATE = new Date(LEAK_PERIOD_SNAPSHOT_IN_MILLISEC - 5000L);
73 private static final Date AFTER_LEAK_PERIOD_DATE = new Date(LEAK_PERIOD_SNAPSHOT_IN_MILLISEC + 5000L);
75 static final String LANGUAGE_KEY_1 = "lKey1";
77 static final int PROJECT_REF = 1;
78 static final int DIR_REF = 12;
79 static final int DIRECTORY_REF = 123;
80 static final int FILE_1_REF = 1231;
81 static final int FILE_2_REF = 1232;
83 static final Component ROOT_PROJECT = builder(Component.Type.PROJECT, PROJECT_REF).setKey("project")
85 builder(DIRECTORY, DIR_REF).setKey("dir")
87 builder(DIRECTORY, DIRECTORY_REF).setKey("directory")
89 builder(FILE, FILE_1_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_KEY_1, 1)).setKey("file1").build(),
90 builder(FILE, FILE_2_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_KEY_1, 1)).setKey("file2").build())
96 public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
99 public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
100 .add(NEW_SECURITY_RATING)
101 .add(NEW_RELIABILITY_RATING);
104 public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
107 public PeriodHolderRule periodsHolder = new PeriodHolderRule().setPeriod(new Period("mode", null, LEAK_PERIOD_SNAPSHOT_IN_MILLISEC, "UUID"));
110 public ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
113 public FillComponentIssuesVisitorRule fillComponentIssuesVisitorRule = new FillComponentIssuesVisitorRule(componentIssuesRepositoryRule, treeRootHolder);
115 private VisitorsCrawler underTest = new VisitorsCrawler(Arrays.asList(fillComponentIssuesVisitorRule,
116 new NewReliabilityAndSecurityRatingMeasuresVisitor(metricRepository, measureRepository, componentIssuesRepositoryRule, periodsHolder)));
119 public void measures_created_for_project_are_all_A_when_they_have_no_FILE_child() {
120 ReportComponent root = builder(PROJECT, 1).build();
121 treeRootHolder.setRoot(root);
123 underTest.visit(root);
125 verifyAddedRawMeasureOnLeakPeriod(1, NEW_SECURITY_RATING_KEY, A);
126 verifyAddedRawMeasureOnLeakPeriod(1, NEW_RELIABILITY_RATING_KEY, A);
130 public void no_measure_if_there_is_no_period() {
131 periodsHolder.setPeriod(null);
132 treeRootHolder.setRoot(builder(PROJECT, 1).build());
134 underTest.visit(treeRootHolder.getRoot());
136 assertThat(measureRepository.getAddedRawMeasures(1).values()).isEmpty();
140 public void compute_new_security_rating() {
141 treeRootHolder.setRoot(ROOT_PROJECT);
142 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
143 newVulnerabilityIssue(10L, MAJOR).setCreationDate(AFTER_LEAK_PERIOD_DATE),
144 // Should not be taken into account
145 newVulnerabilityIssue(1L, MAJOR).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
146 newBugIssue(1L, MAJOR).setCreationDate(AFTER_LEAK_PERIOD_DATE));
147 fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
148 newVulnerabilityIssue(2L, CRITICAL).setCreationDate(AFTER_LEAK_PERIOD_DATE),
149 newVulnerabilityIssue(3L, MINOR).setCreationDate(AFTER_LEAK_PERIOD_DATE),
150 // Should not be taken into account
151 newVulnerabilityIssue(10L, BLOCKER).setCreationDate(AFTER_LEAK_PERIOD_DATE).setResolution(RESOLUTION_FIXED));
152 fillComponentIssuesVisitorRule.setIssues(DIR_REF,
153 newVulnerabilityIssue(7L, BLOCKER).setCreationDate(AFTER_LEAK_PERIOD_DATE));
155 underTest.visit(ROOT_PROJECT);
157 verifyAddedRawMeasureOnLeakPeriod(FILE_1_REF, NEW_SECURITY_RATING_KEY, C);
158 verifyAddedRawMeasureOnLeakPeriod(FILE_2_REF, NEW_SECURITY_RATING_KEY, D);
159 verifyAddedRawMeasureOnLeakPeriod(DIRECTORY_REF, NEW_SECURITY_RATING_KEY, D);
160 verifyAddedRawMeasureOnLeakPeriod(DIR_REF, NEW_SECURITY_RATING_KEY, E);
161 verifyAddedRawMeasureOnLeakPeriod(PROJECT_REF, NEW_SECURITY_RATING_KEY, E);
165 public void compute_new_security_rating_to_A_when_no_issue() {
166 treeRootHolder.setRoot(ROOT_PROJECT);
167 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF);
169 underTest.visit(ROOT_PROJECT);
171 verifyAddedRawMeasureOnLeakPeriod(FILE_1_REF, NEW_SECURITY_RATING_KEY, A);
172 verifyAddedRawMeasureOnLeakPeriod(FILE_2_REF, NEW_SECURITY_RATING_KEY, A);
173 verifyAddedRawMeasureOnLeakPeriod(DIRECTORY_REF, NEW_SECURITY_RATING_KEY, A);
174 verifyAddedRawMeasureOnLeakPeriod(DIR_REF, NEW_SECURITY_RATING_KEY, A);
175 verifyAddedRawMeasureOnLeakPeriod(PROJECT_REF, NEW_SECURITY_RATING_KEY, A);
179 public void compute_new_security_rating_to_A_when_no_new_issue() {
180 treeRootHolder.setRoot(ROOT_PROJECT);
181 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
182 newVulnerabilityIssue(1L, MAJOR).setCreationDate(BEFORE_LEAK_PERIOD_DATE));
184 underTest.visit(ROOT_PROJECT);
186 verifyAddedRawMeasureOnLeakPeriod(FILE_1_REF, NEW_SECURITY_RATING_KEY, A);
187 verifyAddedRawMeasureOnLeakPeriod(FILE_2_REF, NEW_SECURITY_RATING_KEY, A);
188 verifyAddedRawMeasureOnLeakPeriod(DIRECTORY_REF, NEW_SECURITY_RATING_KEY, A);
189 verifyAddedRawMeasureOnLeakPeriod(DIR_REF, NEW_SECURITY_RATING_KEY, A);
190 verifyAddedRawMeasureOnLeakPeriod(PROJECT_REF, NEW_SECURITY_RATING_KEY, A);
194 public void compute_new_reliability_rating() {
195 treeRootHolder.setRoot(ROOT_PROJECT);
196 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
197 newBugIssue(10L, MAJOR).setCreationDate(AFTER_LEAK_PERIOD_DATE),
198 // Should not be taken into account
199 newBugIssue(1L, MAJOR).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
200 newVulnerabilityIssue(1L, MAJOR).setCreationDate(AFTER_LEAK_PERIOD_DATE));
201 fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
202 newBugIssue(2L, CRITICAL).setCreationDate(AFTER_LEAK_PERIOD_DATE),
203 newBugIssue(3L, MINOR).setCreationDate(AFTER_LEAK_PERIOD_DATE),
204 // Should not be taken into account
205 newBugIssue(10L, BLOCKER).setCreationDate(AFTER_LEAK_PERIOD_DATE).setResolution(RESOLUTION_FIXED));
206 fillComponentIssuesVisitorRule.setIssues(DIR_REF,
207 newBugIssue(7L, BLOCKER).setCreationDate(AFTER_LEAK_PERIOD_DATE));
209 underTest.visit(ROOT_PROJECT);
211 verifyAddedRawMeasureOnLeakPeriod(FILE_1_REF, NEW_RELIABILITY_RATING_KEY, C);
212 verifyAddedRawMeasureOnLeakPeriod(FILE_2_REF, NEW_RELIABILITY_RATING_KEY, D);
213 verifyAddedRawMeasureOnLeakPeriod(DIRECTORY_REF, NEW_RELIABILITY_RATING_KEY, D);
214 verifyAddedRawMeasureOnLeakPeriod(DIR_REF, NEW_RELIABILITY_RATING_KEY, E);
215 verifyAddedRawMeasureOnLeakPeriod(PROJECT_REF, NEW_RELIABILITY_RATING_KEY, E);
219 public void compute_new_reliability_rating_to_A_when_no_issue() {
220 treeRootHolder.setRoot(ROOT_PROJECT);
221 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF);
223 underTest.visit(ROOT_PROJECT);
225 verifyAddedRawMeasureOnLeakPeriod(FILE_1_REF, NEW_RELIABILITY_RATING_KEY, A);
226 verifyAddedRawMeasureOnLeakPeriod(FILE_2_REF, NEW_RELIABILITY_RATING_KEY, A);
227 verifyAddedRawMeasureOnLeakPeriod(DIRECTORY_REF, NEW_RELIABILITY_RATING_KEY, A);
228 verifyAddedRawMeasureOnLeakPeriod(DIR_REF, NEW_RELIABILITY_RATING_KEY, A);
229 verifyAddedRawMeasureOnLeakPeriod(PROJECT_REF, NEW_RELIABILITY_RATING_KEY, A);
233 public void compute_new_reliability_rating_to_A_when_no_new_issue() {
234 treeRootHolder.setRoot(ROOT_PROJECT);
235 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
236 newBugIssue(1L, MAJOR).setCreationDate(BEFORE_LEAK_PERIOD_DATE));
238 underTest.visit(ROOT_PROJECT);
240 verifyAddedRawMeasureOnLeakPeriod(FILE_1_REF, NEW_RELIABILITY_RATING_KEY, A);
241 verifyAddedRawMeasureOnLeakPeriod(FILE_2_REF, NEW_RELIABILITY_RATING_KEY, A);
242 verifyAddedRawMeasureOnLeakPeriod(DIRECTORY_REF, NEW_RELIABILITY_RATING_KEY, A);
243 verifyAddedRawMeasureOnLeakPeriod(DIR_REF, NEW_RELIABILITY_RATING_KEY, A);
244 verifyAddedRawMeasureOnLeakPeriod(PROJECT_REF, NEW_RELIABILITY_RATING_KEY, A);
248 public void compute_E_reliability_and_security_rating_on_blocker_issue() {
249 treeRootHolder.setRoot(ROOT_PROJECT);
250 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
251 newBugIssue(10L, BLOCKER).setCreationDate(AFTER_LEAK_PERIOD_DATE),
252 newVulnerabilityIssue(1L, BLOCKER).setCreationDate(AFTER_LEAK_PERIOD_DATE),
253 // Should not be taken into account
254 newBugIssue(1L, MAJOR).setCreationDate(AFTER_LEAK_PERIOD_DATE));
256 underTest.visit(ROOT_PROJECT);
258 verifyAddedRawMeasureOnLeakPeriod(PROJECT_REF, NEW_RELIABILITY_RATING_KEY, E);
259 verifyAddedRawMeasureOnLeakPeriod(PROJECT_REF, NEW_SECURITY_RATING_KEY, E);
263 public void compute_D_reliability_and_security_rating_on_critical_issue() {
264 treeRootHolder.setRoot(ROOT_PROJECT);
265 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
266 newBugIssue(10L, CRITICAL).setCreationDate(AFTER_LEAK_PERIOD_DATE),
267 newVulnerabilityIssue(15L, CRITICAL).setCreationDate(AFTER_LEAK_PERIOD_DATE),
268 // Should not be taken into account
269 newCodeSmellIssue(1L, MAJOR).setCreationDate(AFTER_LEAK_PERIOD_DATE));
271 underTest.visit(ROOT_PROJECT);
273 verifyAddedRawMeasureOnLeakPeriod(PROJECT_REF, NEW_RELIABILITY_RATING_KEY, D);
274 verifyAddedRawMeasureOnLeakPeriod(PROJECT_REF, NEW_SECURITY_RATING_KEY, D);
278 public void compute_C_reliability_and_security_rating_on_major_issue() {
279 treeRootHolder.setRoot(ROOT_PROJECT);
280 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
281 newBugIssue(10L, MAJOR).setCreationDate(AFTER_LEAK_PERIOD_DATE),
282 newVulnerabilityIssue(15L, MAJOR).setCreationDate(AFTER_LEAK_PERIOD_DATE),
283 // Should not be taken into account
284 newCodeSmellIssue(1L, MAJOR).setCreationDate(AFTER_LEAK_PERIOD_DATE));
286 underTest.visit(ROOT_PROJECT);
288 verifyAddedRawMeasureOnLeakPeriod(PROJECT_REF, NEW_RELIABILITY_RATING_KEY, C);
289 verifyAddedRawMeasureOnLeakPeriod(PROJECT_REF, NEW_SECURITY_RATING_KEY, C);
293 public void compute_B_reliability_and_security_rating_on_minor_issue() {
294 treeRootHolder.setRoot(ROOT_PROJECT);
295 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
296 newBugIssue(10L, MINOR).setCreationDate(AFTER_LEAK_PERIOD_DATE),
297 newVulnerabilityIssue(15L, MINOR).setCreationDate(AFTER_LEAK_PERIOD_DATE),
298 // Should not be taken into account
299 newCodeSmellIssue(1L, MAJOR).setCreationDate(AFTER_LEAK_PERIOD_DATE));
301 underTest.visit(ROOT_PROJECT);
303 verifyAddedRawMeasureOnLeakPeriod(PROJECT_REF, NEW_RELIABILITY_RATING_KEY, B);
304 verifyAddedRawMeasureOnLeakPeriod(PROJECT_REF, NEW_SECURITY_RATING_KEY, B);
308 public void compute_A_reliability_and_security_rating_on_info_issue() {
309 treeRootHolder.setRoot(ROOT_PROJECT);
310 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
311 newBugIssue(10L, INFO).setCreationDate(AFTER_LEAK_PERIOD_DATE),
312 newVulnerabilityIssue(15L, INFO).setCreationDate(AFTER_LEAK_PERIOD_DATE),
313 // Should not be taken into account
314 newCodeSmellIssue(1L, MAJOR).setCreationDate(AFTER_LEAK_PERIOD_DATE));
316 underTest.visit(ROOT_PROJECT);
318 verifyAddedRawMeasureOnLeakPeriod(PROJECT_REF, NEW_RELIABILITY_RATING_KEY, A);
319 verifyAddedRawMeasureOnLeakPeriod(PROJECT_REF, NEW_SECURITY_RATING_KEY, A);
322 private void verifyAddedRawMeasureOnLeakPeriod(int componentRef, String metricKey, Rating rating) {
323 MeasureAssert.assertThat(measureRepository.getAddedRawMeasure(componentRef, metricKey))
324 .hasVariation(rating.getIndex());
327 private static DefaultIssue newBugIssue(long effort, String severity) {
328 return newIssue(effort, severity, BUG);
331 private static DefaultIssue newVulnerabilityIssue(long effort, String severity) {
332 return newIssue(effort, severity, VULNERABILITY);
335 private static DefaultIssue newCodeSmellIssue(long effort, String severity) {
336 return newIssue(effort, severity, CODE_SMELL);
339 private static DefaultIssue newIssue(long effort, String severity, RuleType type) {
340 return newIssue(severity, type)
341 .setEffort(Duration.create(effort));
344 private static DefaultIssue newIssue(String severity, RuleType type) {
345 return new DefaultIssue()
346 .setKey(Uuids.create())
347 .setSeverity(severity)
349 .setCreationDate(DEFAULT_ISSUE_CREATION_DATE);