3 * Copyright (C) 2009-2016 SonarSource SA
4 * mailto:contact 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.
21 package org.sonar.server.computation.task.projectanalysis.qualitymodel;
23 import java.util.Arrays;
24 import java.util.Date;
25 import org.junit.Rule;
26 import org.junit.Test;
27 import org.sonar.api.rules.RuleType;
28 import org.sonar.api.utils.Duration;
29 import org.sonar.core.issue.DefaultIssue;
30 import org.sonar.core.util.Uuids;
31 import org.sonar.server.computation.task.projectanalysis.component.Component;
32 import org.sonar.server.computation.task.projectanalysis.component.FileAttributes;
33 import org.sonar.server.computation.task.projectanalysis.component.ReportComponent;
34 import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
35 import org.sonar.server.computation.task.projectanalysis.component.VisitorsCrawler;
36 import org.sonar.server.computation.task.projectanalysis.issue.ComponentIssuesRepositoryRule;
37 import org.sonar.server.computation.task.projectanalysis.issue.FillComponentIssuesVisitorRule;
38 import org.sonar.server.computation.task.projectanalysis.measure.Measure;
39 import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepositoryRule;
40 import org.sonar.server.computation.task.projectanalysis.metric.MetricRepositoryRule;
42 import static org.assertj.core.api.Assertions.assertThat;
43 import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
44 import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING;
45 import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING_KEY;
46 import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING;
47 import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING_KEY;
48 import static org.sonar.api.rule.Severity.BLOCKER;
49 import static org.sonar.api.rule.Severity.CRITICAL;
50 import static org.sonar.api.rule.Severity.INFO;
51 import static org.sonar.api.rule.Severity.MAJOR;
52 import static org.sonar.api.rule.Severity.MINOR;
53 import static org.sonar.api.rules.RuleType.BUG;
54 import static org.sonar.api.rules.RuleType.CODE_SMELL;
55 import static org.sonar.api.rules.RuleType.VULNERABILITY;
56 import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.DIRECTORY;
57 import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.FILE;
58 import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.MODULE;
59 import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT;
60 import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
61 import static org.sonar.server.computation.task.projectanalysis.measure.Measure.newMeasureBuilder;
62 import static org.sonar.server.computation.task.projectanalysis.measure.MeasureRepoEntry.entryOf;
63 import static org.sonar.server.computation.task.projectanalysis.measure.MeasureRepoEntry.toEntries;
64 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating;
65 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.A;
66 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.B;
67 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.C;
68 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.D;
69 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.E;
71 public class ReliabilityAndSecurityRatingMeasuresVisitorForReportTest {
73 static final String LANGUAGE_KEY_1 = "lKey1";
75 static final int PROJECT_REF = 1;
76 static final int MODULE_REF = 12;
77 static final int DIRECTORY_REF = 123;
78 static final int FILE_1_REF = 1231;
79 static final int FILE_2_REF = 1232;
81 static final Component ROOT_PROJECT = builder(Component.Type.PROJECT, PROJECT_REF).setKey("project")
83 builder(MODULE, MODULE_REF).setKey("module")
85 builder(DIRECTORY, DIRECTORY_REF).setKey("directory")
87 builder(FILE, FILE_1_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_KEY_1)).setKey("file1").build(),
88 builder(FILE, FILE_2_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_KEY_1)).setKey("file2").build())
94 public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
97 public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
98 .add(RELIABILITY_RATING)
99 .add(SECURITY_RATING);
102 public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
105 public ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
108 public FillComponentIssuesVisitorRule fillComponentIssuesVisitorRule = new FillComponentIssuesVisitorRule(componentIssuesRepositoryRule, treeRootHolder);
110 VisitorsCrawler underTest = new VisitorsCrawler(
111 Arrays.asList(fillComponentIssuesVisitorRule, new ReliabilityAndSecurityRatingMeasuresVisitor(metricRepository, measureRepository, componentIssuesRepositoryRule)));
114 public void measures_created_for_project_are_all_A_when_they_have_no_FILE_child() {
115 ReportComponent root = builder(PROJECT, 1).build();
116 treeRootHolder.setRoot(root);
118 underTest.visit(root);
120 assertThat(toEntries(measureRepository.getRawMeasures(root)))
122 entryOf(RELIABILITY_RATING_KEY, createRatingMeasure(A)),
123 entryOf(SECURITY_RATING_KEY, createRatingMeasure(A)));
127 public void compute_reliability_rating() throws Exception {
128 treeRootHolder.setRoot(ROOT_PROJECT);
129 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, MAJOR), newBugIssue(1L, MAJOR),
130 // Should not be taken into account
131 newVulnerabilityIssue(5L, MINOR));
132 fillComponentIssuesVisitorRule.setIssues(FILE_2_REF, newBugIssue(2L, CRITICAL), newBugIssue(3L, MINOR),
133 // Should not be taken into account
134 newBugIssue(10L, BLOCKER).setResolution(RESOLUTION_FIXED));
135 fillComponentIssuesVisitorRule.setIssues(MODULE_REF, newBugIssue(7L, BLOCKER));
137 underTest.visit(ROOT_PROJECT);
139 verifyAddedRawMeasure(FILE_1_REF, RELIABILITY_RATING_KEY, C);
140 verifyAddedRawMeasure(FILE_2_REF, RELIABILITY_RATING_KEY, D);
141 verifyAddedRawMeasure(DIRECTORY_REF, RELIABILITY_RATING_KEY, D);
142 verifyAddedRawMeasure(MODULE_REF, RELIABILITY_RATING_KEY, E);
143 verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, E);
147 public void compute_security_rating() throws Exception {
148 treeRootHolder.setRoot(ROOT_PROJECT);
149 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newVulnerabilityIssue(10L, MAJOR), newVulnerabilityIssue(1L, MAJOR),
150 // Should not be taken into account
151 newBugIssue(1L, MAJOR));
152 fillComponentIssuesVisitorRule.setIssues(FILE_2_REF, newVulnerabilityIssue(2L, CRITICAL), newVulnerabilityIssue(3L, MINOR),
153 // Should not be taken into account
154 newVulnerabilityIssue(10L, BLOCKER).setResolution(RESOLUTION_FIXED));
155 fillComponentIssuesVisitorRule.setIssues(MODULE_REF, newVulnerabilityIssue(7L, BLOCKER));
157 underTest.visit(ROOT_PROJECT);
159 verifyAddedRawMeasure(FILE_1_REF, SECURITY_RATING_KEY, C);
160 verifyAddedRawMeasure(FILE_2_REF, SECURITY_RATING_KEY, D);
161 verifyAddedRawMeasure(DIRECTORY_REF, SECURITY_RATING_KEY, D);
162 verifyAddedRawMeasure(MODULE_REF, SECURITY_RATING_KEY, E);
163 verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, E);
167 public void compute_E_reliability_and_security_rating_on_blocker_issue() throws Exception {
168 treeRootHolder.setRoot(ROOT_PROJECT);
169 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, BLOCKER), newVulnerabilityIssue(1L, BLOCKER),
170 // Should not be taken into account
171 newBugIssue(1L, MAJOR));
173 underTest.visit(ROOT_PROJECT);
175 verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, E);
176 verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, E);
180 public void compute_D_reliability_and_security_rating_on_critical_issue() throws Exception {
181 treeRootHolder.setRoot(ROOT_PROJECT);
182 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, CRITICAL), newVulnerabilityIssue(15L, CRITICAL),
183 // Should not be taken into account
184 newCodeSmellIssue(1L, MAJOR));
186 underTest.visit(ROOT_PROJECT);
188 verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, D);
189 verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, D);
193 public void compute_C_reliability_and_security_rating_on_major_issue() throws Exception {
194 treeRootHolder.setRoot(ROOT_PROJECT);
195 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, MAJOR), newVulnerabilityIssue(15L, MAJOR),
196 // Should not be taken into account
197 newCodeSmellIssue(1L, MAJOR));
199 underTest.visit(ROOT_PROJECT);
201 verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, C);
202 verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, C);
206 public void compute_B_reliability_and_security_rating_on_minor_issue() throws Exception {
207 treeRootHolder.setRoot(ROOT_PROJECT);
208 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, MINOR), newVulnerabilityIssue(15L, MINOR),
209 // Should not be taken into account
210 newCodeSmellIssue(1L, MAJOR));
212 underTest.visit(ROOT_PROJECT);
214 verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, B);
215 verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, B);
219 public void compute_A_reliability_and_security_rating_on_info_issue() throws Exception {
220 treeRootHolder.setRoot(ROOT_PROJECT);
221 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, INFO), newVulnerabilityIssue(15L, INFO),
222 // Should not be taken into account
223 newCodeSmellIssue(1L, MAJOR));
225 underTest.visit(ROOT_PROJECT);
227 verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, A);
228 verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, A);
231 private void verifyAddedRawMeasure(int componentRef, String metricKey, Rating rating) {
232 assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(entryOf(metricKey, newMeasureBuilder().create(rating.getIndex(), rating.name())));
235 private static Measure createRatingMeasure(Rating rating) {
236 return newMeasureBuilder().create(rating.getIndex(), rating.name());
239 private static DefaultIssue newBugIssue(long effort, String severity) {
240 return newIssue(effort, severity, BUG);
243 private static DefaultIssue newVulnerabilityIssue(long effort, String severity) {
244 return newIssue(effort, severity, VULNERABILITY);
247 private static DefaultIssue newCodeSmellIssue(long effort, String severity) {
248 return newIssue(effort, severity, CODE_SMELL);
251 private static DefaultIssue newIssue(long effort, String severity, RuleType type) {
252 return newIssue(severity, type)
253 .setEffort(Duration.create(effort));
256 private static DefaultIssue newIssue(String severity, RuleType type) {
257 return new DefaultIssue()
258 .setKey(Uuids.create())
259 .setSeverity(severity)
261 .setCreationDate(new Date(1000l));