3 * Copyright (C) 2009-2023 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.server.measure.live;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.LinkedList;
27 import java.util.List;
29 import java.util.Optional;
31 import javax.annotation.Nullable;
32 import org.junit.Test;
33 import org.sonar.api.issue.Issue;
34 import org.sonar.api.measures.CoreMetrics;
35 import org.sonar.api.measures.Metric;
36 import org.sonar.api.rule.Severity;
37 import org.sonar.api.rules.RuleType;
38 import org.sonar.db.component.ComponentDto;
39 import org.sonar.db.issue.IssueGroupDto;
40 import org.sonar.server.measure.DebtRatingGrid;
41 import org.sonar.server.measure.Rating;
43 import static java.util.Arrays.asList;
44 import static org.assertj.core.api.Assertions.assertThat;
45 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED;
46 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS;
47 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS;
48 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_REVIEW_RATING;
49 import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED;
50 import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS;
51 import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS;
52 import static org.sonar.api.measures.CoreMetrics.SECURITY_REVIEW_RATING;
54 public class MeasureUpdateFormulaFactoryImplTest {
56 private final MeasureUpdateFormulaFactoryImpl underTest = new MeasureUpdateFormulaFactoryImpl();
59 public void getFormulaMetrics_include_the_dependent_metrics() {
60 for (MeasureUpdateFormula formula : underTest.getFormulas()) {
61 assertThat(underTest.getFormulaMetrics()).contains(formula.getMetric());
62 for (Metric<?> dependentMetric : formula.getDependentMetrics()) {
63 assertThat(underTest.getFormulaMetrics()).contains(dependentMetric);
69 public void hierarchy_adding_numbers() {
70 new HierarchyTester(CoreMetrics.VIOLATIONS)
72 .withChildrenValues(2d, 3d)
75 new HierarchyTester(CoreMetrics.BUGS)
77 .withChildrenValues(2d, 3d)
80 new HierarchyTester(CoreMetrics.NEW_BUGS)
86 public void hierarchy_highest_rating() {
87 new HierarchyTester(CoreMetrics.RELIABILITY_RATING)
89 .withChildrenValues(2d, 3d)
90 .expectedRating(Rating.C);
92 // if no children, no need to set a value
93 new HierarchyTester(CoreMetrics.SECURITY_RATING)
95 .expectedResult(null);
97 new HierarchyTester(CoreMetrics.NEW_RELIABILITY_RATING)
99 .withChildrenValues(2d, 3d)
100 .expectedRating(Rating.E);
104 public void hierarchy_combining_other_metrics() {
105 new HierarchyTester(SECURITY_HOTSPOTS_TO_REVIEW_STATUS)
106 .withValue(SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1d)
107 .withChildrenHotspotsCounts(10, 10, 2, 10)
110 new HierarchyTester(SECURITY_HOTSPOTS_REVIEWED_STATUS)
111 .withValue(SECURITY_HOTSPOTS_REVIEWED_STATUS, 1d)
112 .withChildrenHotspotsCounts(2, 10, 10, 10)
115 new HierarchyTester(NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS)
116 .withValue(NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1d)
117 .withChildrenHotspotsCounts(10, 10, 10, 2)
120 new HierarchyTester(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS)
121 .withValue(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, 1d)
122 .withChildrenHotspotsCounts(10, 2, 10, 10)
125 new HierarchyTester(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED)
126 .withValue(SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1d)
127 .withValue(SECURITY_HOTSPOTS_REVIEWED_STATUS, 1d)
128 .expectedResult(50d);
129 new HierarchyTester(CoreMetrics.SECURITY_REVIEW_RATING)
130 .withValue(SECURITY_HOTSPOTS_REVIEWED, 100d)
131 .expectedRating(Rating.A);
133 new HierarchyTester(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED)
134 .withValue(NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1d)
135 .withValue(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, 1d)
136 .expectedResult(50d);
137 new HierarchyTester(CoreMetrics.NEW_SECURITY_REVIEW_RATING)
138 .withValue(NEW_SECURITY_HOTSPOTS_REVIEWED, 0d)
139 .expectedRating(Rating.E);
143 public void test_violations() {
144 withNoIssues().assertThatValueIs(CoreMetrics.VIOLATIONS, 0);
145 with(newGroup(), newGroup().setCount(4)).assertThatValueIs(CoreMetrics.VIOLATIONS, 5);
148 IssueGroupDto resolved = newResolvedGroup(Issue.RESOLUTION_FIXED, Issue.STATUS_RESOLVED);
149 with(newGroup(), newGroup(), resolved).assertThatValueIs(CoreMetrics.VIOLATIONS, 2);
151 // include issues on leak
152 IssueGroupDto onLeak = newGroup().setCount(11).setInLeak(true);
153 with(newGroup(), newGroup(), onLeak).assertThatValueIs(CoreMetrics.VIOLATIONS, 1 + 1 + 11);
157 public void test_bugs() {
158 withNoIssues().assertThatValueIs(CoreMetrics.BUGS, 0);
160 newGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setCount(3),
161 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setCount(5),
163 newResolvedGroup(RuleType.BUG).setCount(7),
165 newGroup(RuleType.CODE_SMELL).setCount(11))
166 .assertThatValueIs(CoreMetrics.BUGS, 3 + 5);
170 public void test_code_smells() {
171 withNoIssues().assertThatValueIs(CoreMetrics.CODE_SMELLS, 0);
173 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setCount(3),
174 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setCount(5),
176 newResolvedGroup(RuleType.CODE_SMELL).setCount(7),
178 newGroup(RuleType.BUG).setCount(11))
179 .assertThatValueIs(CoreMetrics.CODE_SMELLS, 3 + 5);
183 public void test_vulnerabilities() {
184 withNoIssues().assertThatValueIs(CoreMetrics.VULNERABILITIES, 0);
186 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MAJOR).setCount(3),
187 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.CRITICAL).setCount(5),
189 newResolvedGroup(RuleType.VULNERABILITY).setCount(7),
190 // not vulnerabilities
191 newGroup(RuleType.BUG).setCount(11))
192 .assertThatValueIs(CoreMetrics.VULNERABILITIES, 3 + 5);
196 public void test_security_hotspots() {
197 withNoIssues().assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS, 0);
199 newGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Severity.MAJOR).setCount(3),
200 newGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Severity.CRITICAL).setCount(5),
202 newResolvedGroup(RuleType.SECURITY_HOTSPOT).setCount(7),
204 newGroup(RuleType.BUG).setCount(11))
205 .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS, 3 + 5);
209 public void test_security_review_rating() {
211 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
212 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
213 .assertThatValueIs(SECURITY_REVIEW_RATING, Rating.B);
216 .assertThatValueIs(SECURITY_REVIEW_RATING, Rating.A);
220 public void test_security_hotspots_reviewed() {
222 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
223 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
224 .assertThatValueIs(SECURITY_HOTSPOTS_REVIEWED, 75.0);
227 .assertNoValue(SECURITY_HOTSPOTS_REVIEWED);
231 public void test_security_hotspots_reviewed_status() {
233 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
234 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
235 .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS, 3.0);
238 .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS, 0.0);
242 public void test_security_hotspots_to_review_status() {
244 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
245 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
246 .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1.0);
249 .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 0.0);
253 public void count_unresolved_by_severity() {
255 .assertThatValueIs(CoreMetrics.BLOCKER_VIOLATIONS, 0)
256 .assertThatValueIs(CoreMetrics.CRITICAL_VIOLATIONS, 0)
257 .assertThatValueIs(CoreMetrics.MAJOR_VIOLATIONS, 0)
258 .assertThatValueIs(CoreMetrics.MINOR_VIOLATIONS, 0)
259 .assertThatValueIs(CoreMetrics.INFO_VIOLATIONS, 0);
262 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MAJOR).setCount(3),
263 newGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setCount(5),
264 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setCount(7),
265 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setCount(11),
266 // exclude security hotspot
267 newGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Severity.CRITICAL).setCount(15),
269 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(true).setCount(13),
271 newResolvedGroup(RuleType.VULNERABILITY).setSeverity(Severity.INFO).setCount(17),
272 newResolvedGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setCount(19),
273 newResolvedGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Severity.INFO).setCount(21))
274 .assertThatValueIs(CoreMetrics.BLOCKER_VIOLATIONS, 11 + 13)
275 .assertThatValueIs(CoreMetrics.CRITICAL_VIOLATIONS, 7)
276 .assertThatValueIs(CoreMetrics.MAJOR_VIOLATIONS, 3 + 5)
277 .assertThatValueIs(CoreMetrics.MINOR_VIOLATIONS, 0)
278 .assertThatValueIs(CoreMetrics.INFO_VIOLATIONS, 0);
282 public void count_resolved() {
284 .assertThatValueIs(CoreMetrics.FALSE_POSITIVE_ISSUES, 0)
285 .assertThatValueIs(CoreMetrics.WONT_FIX_ISSUES, 0);
288 newResolvedGroup(Issue.RESOLUTION_FIXED, Issue.STATUS_RESOLVED).setCount(3),
289 newResolvedGroup(Issue.RESOLUTION_FALSE_POSITIVE, Issue.STATUS_CLOSED).setCount(5),
290 newResolvedGroup(Issue.RESOLUTION_WONT_FIX, Issue.STATUS_CLOSED).setSeverity(Severity.MAJOR).setCount(7),
291 newResolvedGroup(Issue.RESOLUTION_WONT_FIX, Issue.STATUS_CLOSED).setSeverity(Severity.BLOCKER).setCount(11),
292 newResolvedGroup(Issue.RESOLUTION_REMOVED, Issue.STATUS_CLOSED).setCount(13),
293 // exclude security hotspot
294 newResolvedGroup(Issue.RESOLUTION_WONT_FIX, Issue.STATUS_RESOLVED).setCount(15).setRuleType(RuleType.SECURITY_HOTSPOT.getDbConstant()),
295 // exclude unresolved
296 newGroup(RuleType.VULNERABILITY).setCount(17),
297 newGroup(RuleType.BUG).setCount(19))
298 .assertThatValueIs(CoreMetrics.FALSE_POSITIVE_ISSUES, 5)
299 .assertThatValueIs(CoreMetrics.WONT_FIX_ISSUES, 7 + 11);
303 public void count_by_status() {
305 .assertThatValueIs(CoreMetrics.CONFIRMED_ISSUES, 0)
306 .assertThatValueIs(CoreMetrics.OPEN_ISSUES, 0)
307 .assertThatValueIs(CoreMetrics.REOPENED_ISSUES, 0);
310 newGroup().setStatus(Issue.STATUS_CONFIRMED).setSeverity(Severity.BLOCKER).setCount(3),
311 newGroup().setStatus(Issue.STATUS_CONFIRMED).setSeverity(Severity.INFO).setCount(5),
312 newGroup().setStatus(Issue.STATUS_REOPENED).setCount(7),
313 newGroup(RuleType.CODE_SMELL).setStatus(Issue.STATUS_OPEN).setCount(9),
314 newGroup(RuleType.BUG).setStatus(Issue.STATUS_OPEN).setCount(11),
315 // exclude security hotspot
316 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_OPEN).setCount(12),
317 newResolvedGroup(Issue.RESOLUTION_FALSE_POSITIVE, Issue.STATUS_CLOSED).setCount(13))
318 .assertThatValueIs(CoreMetrics.CONFIRMED_ISSUES, 3 + 5)
319 .assertThatValueIs(CoreMetrics.OPEN_ISSUES, 9 + 11)
320 .assertThatValueIs(CoreMetrics.REOPENED_ISSUES, 7);
324 public void test_technical_debt() {
325 withNoIssues().assertThatValueIs(CoreMetrics.TECHNICAL_DEBT, 0);
328 newGroup(RuleType.CODE_SMELL).setEffort(3.0).setInLeak(false),
329 newGroup(RuleType.CODE_SMELL).setEffort(5.0).setInLeak(true),
330 // exclude security hotspot
331 newGroup(RuleType.SECURITY_HOTSPOT).setEffort(9).setInLeak(true),
332 newGroup(RuleType.SECURITY_HOTSPOT).setEffort(11).setInLeak(false),
334 newGroup(RuleType.BUG).setEffort(7.0),
336 newResolvedGroup(RuleType.CODE_SMELL).setEffort(17.0))
337 .assertThatValueIs(CoreMetrics.TECHNICAL_DEBT, 3.0 + 5.0);
341 public void test_reliability_remediation_effort() {
342 withNoIssues().assertThatValueIs(CoreMetrics.RELIABILITY_REMEDIATION_EFFORT, 0);
345 newGroup(RuleType.BUG).setEffort(3.0),
346 newGroup(RuleType.BUG).setEffort(5.0).setSeverity(Severity.BLOCKER),
348 newGroup(RuleType.CODE_SMELL).setEffort(7.0),
350 newResolvedGroup(RuleType.BUG).setEffort(17.0))
351 .assertThatValueIs(CoreMetrics.RELIABILITY_REMEDIATION_EFFORT, 3.0 + 5.0);
355 public void test_security_remediation_effort() {
356 withNoIssues().assertThatValueIs(CoreMetrics.SECURITY_REMEDIATION_EFFORT, 0);
359 newGroup(RuleType.VULNERABILITY).setEffort(3.0),
360 newGroup(RuleType.VULNERABILITY).setEffort(5.0).setSeverity(Severity.BLOCKER),
362 newGroup(RuleType.CODE_SMELL).setEffort(7.0),
364 newResolvedGroup(RuleType.VULNERABILITY).setEffort(17.0))
365 .assertThatValueIs(CoreMetrics.SECURITY_REMEDIATION_EFFORT, 3.0 + 5.0);
369 public void test_sqale_debt_ratio_and_sqale_rating() {
371 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
372 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
374 // technical_debt not computed
375 with(CoreMetrics.DEVELOPMENT_COST, "0")
376 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
377 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
378 with(CoreMetrics.DEVELOPMENT_COST, "20")
379 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
380 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
382 // development_cost not computed
383 with(CoreMetrics.TECHNICAL_DEBT, 0)
384 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
385 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
386 with(CoreMetrics.TECHNICAL_DEBT, 20)
387 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
388 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
390 // input measures are available
391 with(CoreMetrics.TECHNICAL_DEBT, 20.0)
392 .andText(CoreMetrics.DEVELOPMENT_COST, "0")
393 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
394 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
396 with(CoreMetrics.TECHNICAL_DEBT, 20.0)
397 .andText(CoreMetrics.DEVELOPMENT_COST, "160")
398 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 12.5)
399 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.C);
401 with(CoreMetrics.TECHNICAL_DEBT, 20.0)
402 .andText(CoreMetrics.DEVELOPMENT_COST, "10")
403 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 200.0)
404 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.E);
406 // A is 5% --> min debt is exactly 200*0.05=10
407 with(CoreMetrics.DEVELOPMENT_COST, "200")
408 .and(CoreMetrics.TECHNICAL_DEBT, 10.0)
409 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 5.0)
410 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
412 with(CoreMetrics.TECHNICAL_DEBT, 0.0)
413 .andText(CoreMetrics.DEVELOPMENT_COST, "0")
414 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
415 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
417 with(CoreMetrics.TECHNICAL_DEBT, 0.0)
418 .andText(CoreMetrics.DEVELOPMENT_COST, "80")
419 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0);
421 with(CoreMetrics.TECHNICAL_DEBT, -20.0)
422 .andText(CoreMetrics.DEVELOPMENT_COST, "0")
423 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
424 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
426 // bug, debt can't be negative
427 with(CoreMetrics.TECHNICAL_DEBT, -20.0)
428 .andText(CoreMetrics.DEVELOPMENT_COST, "80")
429 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
430 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
432 // bug, cost can't be negative
433 with(CoreMetrics.TECHNICAL_DEBT, 20.0)
434 .andText(CoreMetrics.DEVELOPMENT_COST, "-80")
435 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
436 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
440 public void test_effort_to_reach_maintainability_rating_A() {
442 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
444 // technical_debt not computed
445 with(CoreMetrics.DEVELOPMENT_COST, 0.0)
446 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
447 with(CoreMetrics.DEVELOPMENT_COST, 20.0)
448 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
450 // development_cost not computed
451 with(CoreMetrics.TECHNICAL_DEBT, 0.0)
452 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
453 with(CoreMetrics.TECHNICAL_DEBT, 20.0)
454 // development cost is considered as zero, so the effort is to reach... zero
455 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 20.0);
458 with(CoreMetrics.DEVELOPMENT_COST, "200")
459 .and(CoreMetrics.TECHNICAL_DEBT, 40.0)
460 // B is 5% --> goal is to reach 200*0.05=10 --> effort is 40-10=30
461 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 40.0 - (200.0 * 0.05));
464 with(CoreMetrics.DEVELOPMENT_COST, "200")
465 .and(CoreMetrics.TECHNICAL_DEBT, 180.0)
466 // B is 5% --> goal is to reach 200*0.05=10 --> effort is 180-10=170
467 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 180.0 - (200.0 * 0.05));
470 with(CoreMetrics.DEVELOPMENT_COST, "200")
471 .and(CoreMetrics.TECHNICAL_DEBT, 8.0)
472 // B is 5% --> goal is to reach 200*0.05=10 --> debt is already at 8 --> effort to reach A is zero
473 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
475 // exactly lower range of B
476 with(CoreMetrics.DEVELOPMENT_COST, "200")
477 .and(CoreMetrics.TECHNICAL_DEBT, 10.0)
478 // B is 5% --> goal is to reach 200*0.05=10 --> debt is 10 --> effort to reach A is zero
479 // FIXME need zero to reach A but effective rating is B !
480 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
484 public void test_reliability_rating() {
486 .assertThatValueIs(CoreMetrics.RELIABILITY_RATING, Rating.A);
489 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setCount(1),
490 newGroup(RuleType.BUG).setSeverity(Severity.MINOR).setCount(5),
491 // excluded, not a bug
492 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setCount(3))
493 // highest severity of bugs is CRITICAL --> D
494 .assertThatValueIs(CoreMetrics.RELIABILITY_RATING, Rating.D);
497 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setCount(3),
498 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.CRITICAL).setCount(5))
500 .assertThatValueIs(CoreMetrics.RELIABILITY_RATING, Rating.A);
504 public void test_security_rating() {
506 .assertThatValueIs(CoreMetrics.SECURITY_RATING, Rating.A);
509 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.CRITICAL).setCount(1),
510 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MINOR).setCount(5),
511 // excluded, not a vulnerability
512 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setCount(3))
513 // highest severity of vulnerabilities is CRITICAL --> D
514 .assertThatValueIs(CoreMetrics.SECURITY_RATING, Rating.D);
517 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setCount(3),
518 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setCount(5))
519 // no vulnerabilities --> A
520 .assertThatValueIs(CoreMetrics.SECURITY_RATING, Rating.A);
524 public void test_new_bugs() {
525 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_BUGS, 0.0);
528 newGroup(RuleType.BUG).setInLeak(false).setSeverity(Severity.MAJOR).setCount(3),
529 newGroup(RuleType.BUG).setInLeak(true).setSeverity(Severity.CRITICAL).setCount(5),
530 newGroup(RuleType.BUG).setInLeak(true).setSeverity(Severity.MINOR).setCount(7),
532 newGroup(RuleType.CODE_SMELL).setInLeak(true).setCount(9),
533 newGroup(RuleType.VULNERABILITY).setInLeak(true).setCount(11))
534 .assertThatLeakValueIs(CoreMetrics.NEW_BUGS, 5 + 7);
539 public void test_new_code_smells() {
540 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_CODE_SMELLS, 0.0);
543 newGroup(RuleType.CODE_SMELL).setInLeak(false).setSeverity(Severity.MAJOR).setCount(3),
544 newGroup(RuleType.CODE_SMELL).setInLeak(true).setSeverity(Severity.CRITICAL).setCount(5),
545 newGroup(RuleType.CODE_SMELL).setInLeak(true).setSeverity(Severity.MINOR).setCount(7),
547 newGroup(RuleType.BUG).setInLeak(true).setCount(9),
548 newGroup(RuleType.VULNERABILITY).setInLeak(true).setCount(11))
549 .assertThatLeakValueIs(CoreMetrics.NEW_CODE_SMELLS, 5 + 7);
553 public void test_new_vulnerabilities() {
554 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_VULNERABILITIES, 0.0);
557 newGroup(RuleType.VULNERABILITY).setInLeak(false).setSeverity(Severity.MAJOR).setCount(3),
558 newGroup(RuleType.VULNERABILITY).setInLeak(true).setSeverity(Severity.CRITICAL).setCount(5),
559 newGroup(RuleType.VULNERABILITY).setInLeak(true).setSeverity(Severity.MINOR).setCount(7),
560 // not vulnerabilities
561 newGroup(RuleType.BUG).setInLeak(true).setCount(9),
562 newGroup(RuleType.CODE_SMELL).setInLeak(true).setCount(11))
563 .assertThatLeakValueIs(CoreMetrics.NEW_VULNERABILITIES, 5 + 7);
567 public void test_new_security_hotspots() {
568 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS, 0);
571 newGroup(RuleType.SECURITY_HOTSPOT).setInLeak(false).setSeverity(Severity.MAJOR).setCount(3),
572 newGroup(RuleType.SECURITY_HOTSPOT).setInLeak(true).setSeverity(Severity.CRITICAL).setCount(5),
573 newGroup(RuleType.SECURITY_HOTSPOT).setInLeak(true).setSeverity(Severity.MINOR).setCount(7),
575 newGroup(RuleType.BUG).setInLeak(true).setCount(9),
576 newGroup(RuleType.CODE_SMELL).setInLeak(true).setCount(11))
577 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS, 5 + 7);
581 public void test_new_violations() {
582 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_VIOLATIONS, 0.0);
585 newGroup(RuleType.BUG).setInLeak(true).setCount(5),
586 newGroup(RuleType.CODE_SMELL).setInLeak(true).setCount(7),
587 newGroup(RuleType.VULNERABILITY).setInLeak(true).setCount(9),
589 newGroup(RuleType.BUG).setInLeak(false).setCount(11),
590 newGroup(RuleType.CODE_SMELL).setInLeak(false).setCount(13),
591 newGroup(RuleType.VULNERABILITY).setInLeak(false).setCount(17))
592 .assertThatLeakValueIs(CoreMetrics.NEW_VIOLATIONS, 5 + 7 + 9);
596 public void test_new_blocker_violations() {
598 .assertThatLeakValueIs(CoreMetrics.NEW_BLOCKER_VIOLATIONS, 0.0);
601 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(true).setCount(3),
602 newGroup(RuleType.BUG).setSeverity(Severity.BLOCKER).setInLeak(true).setCount(5),
603 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.BLOCKER).setInLeak(true).setCount(7),
605 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(9),
607 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(false).setCount(11),
608 newGroup(RuleType.BUG).setSeverity(Severity.BLOCKER).setInLeak(false).setCount(13))
609 .assertThatLeakValueIs(CoreMetrics.NEW_BLOCKER_VIOLATIONS, 3 + 5 + 7);
613 public void test_new_critical_violations() {
615 .assertThatLeakValueIs(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 0.0);
618 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(3),
619 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(5),
620 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(7),
622 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setInLeak(true).setCount(9),
624 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(false).setCount(11),
625 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setInLeak(false).setCount(13))
626 .assertThatLeakValueIs(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 3 + 5 + 7);
630 public void test_new_major_violations() {
632 .assertThatLeakValueIs(CoreMetrics.NEW_MAJOR_VIOLATIONS, 0.0);
635 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setInLeak(true).setCount(3),
636 newGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setInLeak(true).setCount(5),
637 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MAJOR).setInLeak(true).setCount(7),
639 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(9),
641 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setInLeak(false).setCount(11),
642 newGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setInLeak(false).setCount(13))
643 .assertThatLeakValueIs(CoreMetrics.NEW_MAJOR_VIOLATIONS, 3 + 5 + 7);
647 public void test_new_minor_violations() {
649 .assertThatLeakValueIs(CoreMetrics.NEW_MINOR_VIOLATIONS, 0.0);
652 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MINOR).setInLeak(true).setCount(3),
653 newGroup(RuleType.BUG).setSeverity(Severity.MINOR).setInLeak(true).setCount(5),
654 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MINOR).setInLeak(true).setCount(7),
656 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(9),
658 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MINOR).setInLeak(false).setCount(11),
659 newGroup(RuleType.BUG).setSeverity(Severity.MINOR).setInLeak(false).setCount(13))
660 .assertThatLeakValueIs(CoreMetrics.NEW_MINOR_VIOLATIONS, 3 + 5 + 7);
664 public void test_new_info_violations() {
666 .assertThatLeakValueIs(CoreMetrics.NEW_INFO_VIOLATIONS, 0.0);
669 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.INFO).setInLeak(true).setCount(3),
670 newGroup(RuleType.BUG).setSeverity(Severity.INFO).setInLeak(true).setCount(5),
671 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.INFO).setInLeak(true).setCount(7),
673 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(9),
675 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.INFO).setInLeak(false).setCount(11),
676 newGroup(RuleType.BUG).setSeverity(Severity.INFO).setInLeak(false).setCount(13))
677 .assertThatLeakValueIs(CoreMetrics.NEW_INFO_VIOLATIONS, 3 + 5 + 7);
681 public void test_new_technical_debt() {
682 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0);
685 newGroup(RuleType.CODE_SMELL).setEffort(3.0).setInLeak(true),
687 newGroup(RuleType.CODE_SMELL).setEffort(5.0).setInLeak(false),
689 newGroup(RuleType.SECURITY_HOTSPOT).setEffort(9.0).setInLeak(true),
690 newGroup(RuleType.BUG).setEffort(7.0).setInLeak(true),
692 newResolvedGroup(RuleType.CODE_SMELL).setEffort(17.0).setInLeak(true))
693 .assertThatLeakValueIs(CoreMetrics.NEW_TECHNICAL_DEBT, 3.0);
697 public void test_new_reliability_remediation_effort() {
698 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_RELIABILITY_REMEDIATION_EFFORT, 0.0);
701 newGroup(RuleType.BUG).setEffort(3.0).setInLeak(true),
703 newGroup(RuleType.BUG).setEffort(5.0).setInLeak(false),
705 newGroup(RuleType.CODE_SMELL).setEffort(7.0).setInLeak(true),
707 newResolvedGroup(RuleType.BUG).setEffort(17.0).setInLeak(true))
708 .assertThatLeakValueIs(CoreMetrics.NEW_RELIABILITY_REMEDIATION_EFFORT, 3.0);
712 public void test_new_security_remediation_effort() {
713 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_REMEDIATION_EFFORT, 0.0);
716 newGroup(RuleType.VULNERABILITY).setEffort(3.0).setInLeak(true),
718 newGroup(RuleType.VULNERABILITY).setEffort(5.0).setInLeak(false),
720 newGroup(RuleType.CODE_SMELL).setEffort(7.0).setInLeak(true),
722 newResolvedGroup(RuleType.VULNERABILITY).setEffort(17.0).setInLeak(true))
723 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_REMEDIATION_EFFORT, 3.0);
727 public void test_new_reliability_rating() {
728 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_RELIABILITY_RATING, Rating.A);
731 newGroup(RuleType.BUG).setSeverity(Severity.INFO).setCount(3).setInLeak(true),
732 newGroup(RuleType.BUG).setSeverity(Severity.MINOR).setCount(1).setInLeak(true),
734 newGroup(RuleType.BUG).setSeverity(Severity.BLOCKER).setInLeak(false),
736 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(true),
738 newResolvedGroup(RuleType.BUG).setSeverity(Severity.BLOCKER).setInLeak(true))
739 // highest severity of bugs on leak period is minor -> B
740 .assertThatLeakValueIs(CoreMetrics.NEW_RELIABILITY_RATING, Rating.B);
744 public void test_new_security_rating() {
745 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_RATING, Rating.A);
748 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.INFO).setCount(3).setInLeak(true),
749 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MINOR).setCount(1).setInLeak(true),
751 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.BLOCKER).setInLeak(false),
753 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(true),
755 newResolvedGroup(RuleType.VULNERABILITY).setSeverity(Severity.BLOCKER).setInLeak(true))
756 // highest severity of bugs on leak period is minor -> B
757 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_RATING, Rating.B);
761 public void test_new_security_review_rating() {
763 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3).setInLeak(true),
764 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
766 newGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Issue.STATUS_TO_REVIEW).setInLeak(false))
767 .assertThatLeakValueIs(NEW_SECURITY_REVIEW_RATING, Rating.B);
770 .assertThatLeakValueIs(NEW_SECURITY_REVIEW_RATING, Rating.A);
774 public void test_new_security_hotspots_reviewed() {
776 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3).setInLeak(true),
777 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
779 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(5).setInLeak(false))
780 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED, 75.0);
783 .assertNoLeakValue(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED);
787 public void test_new_security_hotspots_reviewed_status() {
789 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3).setInLeak(true),
790 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
792 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(5).setInLeak(false))
793 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, 3.0);
796 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, 0.0);
800 public void test_new_security_hotspots_to_review_status() {
802 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3).setInLeak(true),
803 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
805 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(5).setInLeak(false))
806 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1.0);
809 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 0.0);
813 public void test_new_sqale_debt_ratio_and_new_maintainability_rating() {
815 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
816 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
818 // technical_debt not computed
819 with(CoreMetrics.NEW_DEVELOPMENT_COST, 0)
820 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
821 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
822 with(CoreMetrics.NEW_DEVELOPMENT_COST, 20)
823 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
824 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
826 // development_cost not computed
827 with(CoreMetrics.NEW_TECHNICAL_DEBT, 0)
828 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
829 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
830 with(CoreMetrics.NEW_TECHNICAL_DEBT, 20)
831 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
832 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
834 // input measures are available
835 with(CoreMetrics.NEW_TECHNICAL_DEBT, 20.0)
836 .and(CoreMetrics.NEW_DEVELOPMENT_COST, 0.0)
837 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
838 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
840 with(CoreMetrics.NEW_TECHNICAL_DEBT, 20.0)
841 .and(CoreMetrics.NEW_DEVELOPMENT_COST, 160.0)
842 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 12.5)
843 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.C);
845 with(CoreMetrics.NEW_TECHNICAL_DEBT, 20.0)
846 .and(CoreMetrics.NEW_DEVELOPMENT_COST, 10.0D)
847 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 200.0)
848 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.E);
850 // A is 5% --> min debt is exactly 200*0.05=10
851 with(CoreMetrics.NEW_DEVELOPMENT_COST, 200.0)
852 .and(CoreMetrics.NEW_TECHNICAL_DEBT, 10.0)
853 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 5.0)
854 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
856 with(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0)
857 .and(CoreMetrics.NEW_DEVELOPMENT_COST, 0.0)
858 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
859 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
861 with(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0)
862 .and(CoreMetrics.NEW_DEVELOPMENT_COST, 80.0)
863 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0);
865 with(CoreMetrics.NEW_TECHNICAL_DEBT, -20.0)
866 .and(CoreMetrics.NEW_DEVELOPMENT_COST, 0.0)
867 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
868 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
870 // bug, debt can't be negative
871 with(CoreMetrics.NEW_TECHNICAL_DEBT, -20.0)
872 .and(CoreMetrics.NEW_DEVELOPMENT_COST, 80.0)
873 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
874 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
876 // bug, cost can't be negative
877 with(CoreMetrics.NEW_TECHNICAL_DEBT, 20.0)
878 .and(CoreMetrics.NEW_DEVELOPMENT_COST, -80.0)
879 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
880 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
883 private Verifier with(IssueGroupDto... groups) {
884 return new Verifier(groups);
887 private Verifier withNoIssues() {
888 return new Verifier(new IssueGroupDto[0]);
891 private Verifier with(Metric metric, double value) {
892 return new Verifier(new IssueGroupDto[0]).and(metric, value);
895 private Verifier with(Metric metric, String value) {
896 return new Verifier(new IssueGroupDto[0]).andText(metric, value);
899 private class Verifier {
900 private final IssueGroupDto[] groups;
901 private final InitialValues initialValues = new InitialValues();
903 private Verifier(IssueGroupDto[] groups) {
904 this.groups = groups;
907 Verifier and(Metric metric, double value) {
908 this.initialValues.values.put(metric, value);
912 Verifier andText(Metric metric, String value) {
913 this.initialValues.text.put(metric, value);
917 Verifier assertThatValueIs(Metric metric, double expectedValue) {
918 TestContext context = run(metric, false);
919 assertThat(context.doubleValue).isNotNull().isEqualTo(expectedValue);
923 Verifier assertThatLeakValueIs(Metric metric, double expectedValue) {
924 TestContext context = run(metric, true);
925 assertThat(context.doubleValue).isNotNull().isEqualTo(expectedValue);
929 Verifier assertThatLeakValueIs(Metric metric, Rating expectedRating) {
930 TestContext context = run(metric, true);
931 assertThat(context.ratingValue).isNotNull().isEqualTo(expectedRating);
935 Verifier assertNoLeakValue(Metric metric) {
936 TestContext context = run(metric, true);
937 assertThat(context.ratingValue).isNull();
941 Verifier assertThatValueIs(Metric metric, Rating expectedValue) {
942 TestContext context = run(metric, false);
943 assertThat(context.ratingValue).isNotNull().isEqualTo(expectedValue);
947 Verifier assertNoValue(Metric metric) {
948 TestContext context = run(metric, false);
949 assertThat(context.ratingValue).isNull();
953 private TestContext run(Metric metric, boolean expectLeakFormula) {
954 MeasureUpdateFormula formula = underTest.getFormulas().stream()
955 .filter(f -> f.getMetric().getKey().equals(metric.getKey()))
958 assertThat(formula.isOnLeak()).isEqualTo(expectLeakFormula);
959 TestContext context = new TestContext(formula.getDependentMetrics(), initialValues);
960 formula.compute(context, newIssueCounter(groups));
965 private static IssueCounter newIssueCounter(IssueGroupDto... issues) {
966 return new IssueCounter(asList(issues));
969 private static IssueGroupDto newGroup() {
970 return newGroup(RuleType.CODE_SMELL);
973 private static IssueGroupDto newGroup(RuleType ruleType) {
974 IssueGroupDto dto = new IssueGroupDto();
975 // set non-null fields
976 dto.setRuleType(ruleType.getDbConstant());
979 dto.setSeverity(Severity.INFO);
980 dto.setStatus(Issue.STATUS_OPEN);
981 dto.setInLeak(false);
985 private static IssueGroupDto newResolvedGroup(RuleType ruleType) {
986 return newGroup(ruleType).setResolution(Issue.RESOLUTION_FALSE_POSITIVE).setStatus(Issue.STATUS_CLOSED);
989 private static IssueGroupDto newResolvedGroup(String resolution, String status) {
990 return newGroup().setResolution(resolution).setStatus(status);
993 private static class TestContext implements MeasureUpdateFormula.Context {
994 private final Set<Metric> dependentMetrics;
995 private final InitialValues initialValues;
996 private Double doubleValue;
997 private Rating ratingValue;
999 private TestContext(Collection<Metric> dependentMetrics, InitialValues initialValues) {
1000 this.dependentMetrics = new HashSet<>(dependentMetrics);
1001 this.initialValues = initialValues;
1005 public List<Double> getChildrenValues() {
1006 return initialValues.childrenValues;
1010 public long getChildrenHotspotsReviewed() {
1011 return initialValues.childrenHotspotsReviewed;
1015 public long getChildrenHotspotsToReview() {
1016 return initialValues.childrenHotspotsToReview;
1020 public long getChildrenNewHotspotsReviewed() {
1021 return initialValues.childrenNewHotspotsReviewed;
1025 public long getChildrenNewHotspotsToReview() {
1026 return initialValues.childrenNewHotspotsToReview;
1030 public ComponentDto getComponent() {
1031 throw new UnsupportedOperationException();
1035 public DebtRatingGrid getDebtRatingGrid() {
1036 return new DebtRatingGrid(new double[] {0.05, 0.1, 0.2, 0.5});
1040 public Optional<Double> getValue(Metric metric) {
1041 if (!dependentMetrics.contains(metric)) {
1042 throw new IllegalStateException("Metric " + metric.getKey() + " is not declared as a dependency");
1044 if (initialValues.values.containsKey(metric)) {
1045 return Optional.of(initialValues.values.get(metric));
1047 return Optional.empty();
1051 public Optional<String> getText(Metric metric) {
1052 if (initialValues.text.containsKey(metric)) {
1053 return Optional.of(initialValues.text.get(metric));
1055 return Optional.empty();
1059 public void setValue(double value) {
1060 this.doubleValue = value;
1064 public void setValue(Rating value) {
1065 this.ratingValue = value;
1069 private class InitialValues {
1070 private final Map<Metric, Double> values = new HashMap<>();
1071 private final List<Double> childrenValues = new ArrayList<>();
1072 private final Map<Metric, String> text = new HashMap<>();
1073 private long childrenHotspotsReviewed = 0;
1074 private long childrenNewHotspotsReviewed = 0;
1075 private long childrenHotspotsToReview = 0;
1076 private long childrenNewHotspotsToReview = 0;
1080 private class HierarchyTester {
1081 private final Metric metric;
1082 private final InitialValues initialValues;
1083 private final MeasureUpdateFormula formula;
1085 public HierarchyTester(Metric metric) {
1086 this.metric = metric;
1087 this.initialValues = new InitialValues();
1088 this.formula = underTest.getFormulas().stream().filter(f -> f.getMetric().equals(metric)).findAny().get();
1091 public HierarchyTester withValue(Metric metric, Double value) {
1092 this.initialValues.values.put(metric, value);
1096 public HierarchyTester withChildrenHotspotsCounts(long childrenHotspotsReviewed, long childrenNewHotspotsReviewed, long childrenHotspotsToReview,
1097 long childrenNewHotspotsToReview) {
1098 this.initialValues.childrenHotspotsReviewed = childrenHotspotsReviewed;
1099 this.initialValues.childrenNewHotspotsReviewed = childrenNewHotspotsReviewed;
1100 this.initialValues.childrenHotspotsToReview = childrenHotspotsToReview;
1101 this.initialValues.childrenNewHotspotsToReview = childrenNewHotspotsToReview;
1105 public HierarchyTester withValue(Double value) {
1106 return withValue(metric, value);
1109 public HierarchyTester withChildrenValues(Double... values) {
1110 this.initialValues.childrenValues.addAll(asList(values));
1114 public HierarchyTester expectedResult(@Nullable Double expected) {
1115 TestContext ctx = run();
1116 assertThat(ctx.doubleValue).isEqualTo(expected);
1120 public HierarchyTester expectedRating(@Nullable Rating rating) {
1121 TestContext ctx = run();
1122 assertThat(ctx.ratingValue).isEqualTo(rating);
1126 private TestContext run() {
1127 List<Metric> deps = new LinkedList<>(formula.getDependentMetrics());
1128 deps.add(formula.getMetric());
1129 deps.addAll(initialValues.values.keySet());
1130 deps.addAll(initialValues.text.keySet());
1131 TestContext context = new TestContext(deps, initialValues);
1132 formula.computeHierarchy(context);