3 * Copyright (C) 2009-2020 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 javax.annotation.Nullable;
23 import org.junit.Rule;
24 import org.junit.Test;
25 import org.sonar.api.rules.RuleType;
26 import org.sonar.ce.task.projectanalysis.component.Component;
27 import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
28 import org.sonar.ce.task.projectanalysis.component.VisitorsCrawler;
29 import org.sonar.ce.task.projectanalysis.issue.ComponentIssuesRepositoryRule;
30 import org.sonar.ce.task.projectanalysis.issue.FillComponentIssuesVisitorRule;
31 import org.sonar.ce.task.projectanalysis.measure.Measure;
32 import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
33 import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
34 import org.sonar.core.issue.DefaultIssue;
35 import org.sonar.core.util.Uuids;
36 import org.sonar.server.measure.Rating;
38 import static java.util.Arrays.asList;
39 import static org.assertj.core.api.Assertions.assertThat;
40 import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
41 import static org.sonar.api.issue.Issue.RESOLUTION_SAFE;
42 import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED;
43 import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_KEY;
44 import static org.sonar.api.measures.CoreMetrics.SECURITY_REVIEW_RATING;
45 import static org.sonar.api.measures.CoreMetrics.SECURITY_REVIEW_RATING_KEY;
46 import static org.sonar.api.rule.Severity.MAJOR;
47 import static org.sonar.api.rule.Severity.MINOR;
48 import static org.sonar.ce.task.projectanalysis.component.Component.Type.DIRECTORY;
49 import static org.sonar.ce.task.projectanalysis.component.Component.Type.FILE;
50 import static org.sonar.ce.task.projectanalysis.component.ReportComponent.builder;
51 import static org.sonar.core.issue.DefaultIssue.STATUS_REVIEWED;
52 import static org.sonar.core.issue.DefaultIssue.STATUS_TO_REVIEW;
53 import static org.sonar.server.measure.Rating.A;
54 import static org.sonar.server.measure.Rating.B;
55 import static org.sonar.server.measure.Rating.C;
56 import static org.sonar.server.measure.Rating.D;
57 import static org.sonar.server.measure.Rating.E;
59 public class SecurityReviewMeasuresVisitorTest {
61 private static final int PROJECT_REF = 1;
62 private static final int ROOT_DIR_REF = 12;
63 private static final int DIRECTORY_REF = 123;
64 private static final int FILE_1_REF = 1231;
65 private static final int FILE_2_REF = 1232;
67 static final Component ROOT_PROJECT = builder(Component.Type.PROJECT, PROJECT_REF).setKey("project")
69 builder(DIRECTORY, ROOT_DIR_REF).setKey("dir")
71 builder(DIRECTORY, DIRECTORY_REF).setKey("directory")
73 builder(FILE, FILE_1_REF).setKey("file1").build(),
74 builder(FILE, FILE_2_REF).setKey("file2").build())
80 public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
82 public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
83 .add(SECURITY_REVIEW_RATING)
84 .add(SECURITY_HOTSPOTS_REVIEWED);
86 public ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
88 public FillComponentIssuesVisitorRule fillComponentIssuesVisitorRule = new FillComponentIssuesVisitorRule(componentIssuesRepositoryRule, treeRootHolder);
90 public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
92 private VisitorsCrawler underTest = new VisitorsCrawler(asList(fillComponentIssuesVisitorRule,
93 new SecurityReviewMeasuresVisitor(componentIssuesRepositoryRule, measureRepository, metricRepository)));
96 public void compute_measures_when_100_percent_hotspots_reviewed() {
97 treeRootHolder.setRoot(ROOT_PROJECT);
98 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
99 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
100 // Should not be taken into account
102 fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
103 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
104 newHotspot(STATUS_REVIEWED, RESOLUTION_SAFE),
107 underTest.visit(ROOT_PROJECT);
109 verifyMeasures(FILE_1_REF, A, 100.0);
110 verifyMeasures(FILE_2_REF, A, 100.0);
111 verifyMeasures(DIRECTORY_REF, A, 100.0);
112 verifyMeasures(ROOT_DIR_REF, A, 100.0);
113 verifyMeasures(PROJECT_REF, A, 100.0);
117 public void compute_measures_when_more_than_80_percent_hotspots_reviewed() {
118 treeRootHolder.setRoot(ROOT_PROJECT);
119 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
120 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
121 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
122 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
123 // Should not be taken into account
125 fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
126 newHotspot(STATUS_TO_REVIEW, null),
127 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
128 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
129 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
130 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
133 underTest.visit(ROOT_PROJECT);
135 verifyMeasures(FILE_1_REF, A, 100.0);
136 verifyMeasures(FILE_2_REF, A, 80.0);
137 verifyMeasures(DIRECTORY_REF, A, 87.5);
138 verifyMeasures(ROOT_DIR_REF, A, 87.5);
139 verifyMeasures(PROJECT_REF, A, 87.5);
143 public void compute_measures_when_more_than_70_percent_hotspots_reviewed() {
144 treeRootHolder.setRoot(ROOT_PROJECT);
145 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
146 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
147 // Should not be taken into account
149 fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
150 newHotspot(STATUS_TO_REVIEW, null),
151 newHotspot(STATUS_TO_REVIEW, null),
152 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
153 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
154 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
155 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
156 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
159 underTest.visit(ROOT_PROJECT);
161 verifyMeasures(FILE_1_REF, A, 100.0);
162 verifyMeasures(FILE_2_REF, B, 71.4);
163 verifyMeasures(DIRECTORY_REF, B, 75.0);
164 verifyMeasures(ROOT_DIR_REF, B, 75.0);
165 verifyMeasures(PROJECT_REF, B, 75.0);
169 public void compute_measures_when_more_than_50_percent_hotspots_reviewed() {
170 treeRootHolder.setRoot(ROOT_PROJECT);
171 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
172 newHotspot(STATUS_TO_REVIEW, null),
173 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
174 // Should not be taken into account
176 fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
177 newHotspot(STATUS_TO_REVIEW, null),
178 newHotspot(STATUS_TO_REVIEW, null),
179 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
180 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
181 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
184 underTest.visit(ROOT_PROJECT);
186 verifyMeasures(FILE_1_REF, C, 50.0);
187 verifyMeasures(FILE_2_REF, C, 60.0);
188 verifyMeasures(DIRECTORY_REF, C, 57.1);
189 verifyMeasures(ROOT_DIR_REF, C, 57.1);
190 verifyMeasures(PROJECT_REF, C, 57.1);
194 public void compute_measures_when_more_30_than_percent_hotspots_reviewed() {
195 treeRootHolder.setRoot(ROOT_PROJECT);
196 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
197 newHotspot(STATUS_TO_REVIEW, null),
198 newHotspot(STATUS_TO_REVIEW, null),
199 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
200 // Should not be taken into account
202 fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
203 newHotspot(STATUS_TO_REVIEW, null),
204 newHotspot(STATUS_TO_REVIEW, null),
205 newHotspot(STATUS_TO_REVIEW, null),
206 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
207 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
210 underTest.visit(ROOT_PROJECT);
212 verifyMeasures(FILE_1_REF, D, 33.3);
213 verifyMeasures(FILE_2_REF, D, 40.0);
214 verifyMeasures(DIRECTORY_REF, D, 37.5);
215 verifyMeasures(ROOT_DIR_REF, D, 37.5);
216 verifyMeasures(PROJECT_REF, D, 37.5);
220 public void compute_measures_when_less_than_30_percent_hotspots_reviewed() {
221 treeRootHolder.setRoot(ROOT_PROJECT);
222 fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
223 newHotspot(STATUS_TO_REVIEW, null),
224 newHotspot(STATUS_TO_REVIEW, null),
225 newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
226 // Should not be taken into account
228 fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
229 newHotspot(STATUS_TO_REVIEW, null),
230 newHotspot(STATUS_TO_REVIEW, null),
231 newHotspot(STATUS_TO_REVIEW, null),
234 underTest.visit(ROOT_PROJECT);
236 verifyMeasures(FILE_1_REF, D, 33.3);
237 verifyMeasures(FILE_2_REF, E, 0.0);
238 verifyMeasures(DIRECTORY_REF, E, 16.7);
239 verifyMeasures(ROOT_DIR_REF, E, 16.7);
240 verifyMeasures(PROJECT_REF, E, 16.7);
244 public void compute_A_rating_and_100_percent_when_no_hotspot() {
245 treeRootHolder.setRoot(ROOT_PROJECT);
247 underTest.visit(ROOT_PROJECT);
249 verifyMeasures(PROJECT_REF, A, 100.0);
252 private void verifyMeasures(int componentRef, Rating expectedReviewRating, double expectedHotspotsReviewed) {
253 verifySecurityReviewRating(componentRef, expectedReviewRating);
254 verifySecurityHotspotsReviewed(componentRef, expectedHotspotsReviewed);
257 private void verifySecurityReviewRating(int componentRef, Rating rating) {
258 Measure measure = measureRepository.getAddedRawMeasure(componentRef, SECURITY_REVIEW_RATING_KEY).get();
259 assertThat(measure.getIntValue()).isEqualTo(rating.getIndex());
260 assertThat(measure.getData()).isEqualTo(rating.name());
263 private void verifySecurityHotspotsReviewed(int componentRef, double percent) {
264 assertThat(measureRepository.getAddedRawMeasure(componentRef, SECURITY_HOTSPOTS_REVIEWED_KEY).get().getDoubleValue()).isEqualTo(percent);
267 private static DefaultIssue newHotspot(String status, @Nullable String resolution) {
268 return new DefaultIssue()
269 .setKey(Uuids.create())
272 .setResolution(resolution)
273 .setType(RuleType.SECURITY_HOTSPOT);
276 private static DefaultIssue newIssue() {
277 return new DefaultIssue()
278 .setKey(Uuids.create())
280 .setType(RuleType.BUG);