]> source.dussan.org Git - sonarqube.git/blob
7e259ea5998d40ff2dd8e5ab858e36961320a23d
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2020 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.qualitymodel;
21
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;
37
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;
58
59 public class SecurityReviewMeasuresVisitorTest {
60
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;
66
67   static final Component ROOT_PROJECT = builder(Component.Type.PROJECT, PROJECT_REF).setKey("project")
68     .addChildren(
69       builder(DIRECTORY, ROOT_DIR_REF).setKey("dir")
70         .addChildren(
71           builder(DIRECTORY, DIRECTORY_REF).setKey("directory")
72             .addChildren(
73               builder(FILE, FILE_1_REF).setKey("file1").build(),
74               builder(FILE, FILE_2_REF).setKey("file2").build())
75             .build())
76         .build())
77     .build();
78
79   @Rule
80   public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
81   @Rule
82   public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
83     .add(SECURITY_REVIEW_RATING)
84     .add(SECURITY_HOTSPOTS_REVIEWED);
85   @Rule
86   public ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
87   @Rule
88   public FillComponentIssuesVisitorRule fillComponentIssuesVisitorRule = new FillComponentIssuesVisitorRule(componentIssuesRepositoryRule, treeRootHolder);
89   @Rule
90   public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
91
92   private VisitorsCrawler underTest = new VisitorsCrawler(asList(fillComponentIssuesVisitorRule,
93     new SecurityReviewMeasuresVisitor(componentIssuesRepositoryRule, measureRepository, metricRepository)));
94
95   @Test
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
101       newIssue());
102     fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
103       newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
104       newHotspot(STATUS_REVIEWED, RESOLUTION_SAFE),
105       newIssue());
106
107     underTest.visit(ROOT_PROJECT);
108
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);
114   }
115
116   @Test
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
124       newIssue());
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),
131       newIssue());
132
133     underTest.visit(ROOT_PROJECT);
134
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);
140   }
141
142   @Test
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
148       newIssue());
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),
157       newIssue());
158
159     underTest.visit(ROOT_PROJECT);
160
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);
166   }
167
168   @Test
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
175       newIssue());
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),
182       newIssue());
183
184     underTest.visit(ROOT_PROJECT);
185
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);
191   }
192
193   @Test
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
201       newIssue());
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),
208       newIssue());
209
210     underTest.visit(ROOT_PROJECT);
211
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);
217   }
218
219   @Test
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
227       newIssue());
228     fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
229       newHotspot(STATUS_TO_REVIEW, null),
230       newHotspot(STATUS_TO_REVIEW, null),
231       newHotspot(STATUS_TO_REVIEW, null),
232       newIssue());
233
234     underTest.visit(ROOT_PROJECT);
235
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);
241   }
242
243   @Test
244   public void compute_A_rating_and_100_percent_when_no_hotspot() {
245     treeRootHolder.setRoot(ROOT_PROJECT);
246
247     underTest.visit(ROOT_PROJECT);
248
249     verifyMeasures(PROJECT_REF, A, 100.0);
250   }
251
252   private void verifyMeasures(int componentRef, Rating expectedReviewRating, double expectedHotspotsReviewed) {
253     verifySecurityReviewRating(componentRef, expectedReviewRating);
254     verifySecurityHotspotsReviewed(componentRef, expectedHotspotsReviewed);
255   }
256
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());
261   }
262
263   private void verifySecurityHotspotsReviewed(int componentRef, double percent) {
264     assertThat(measureRepository.getAddedRawMeasure(componentRef, SECURITY_HOTSPOTS_REVIEWED_KEY).get().getDoubleValue()).isEqualTo(percent);
265   }
266
267   private static DefaultIssue newHotspot(String status, @Nullable String resolution) {
268     return new DefaultIssue()
269       .setKey(Uuids.create())
270       .setSeverity(MINOR)
271       .setStatus(status)
272       .setResolution(resolution)
273       .setType(RuleType.SECURITY_HOTSPOT);
274   }
275
276   private static DefaultIssue newIssue() {
277     return new DefaultIssue()
278       .setKey(Uuids.create())
279       .setSeverity(MAJOR)
280       .setType(RuleType.BUG);
281   }
282
283 }