3 * Copyright (C) 2009-2022 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(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED)
106 .withValue(SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1d)
107 .withValue(SECURITY_HOTSPOTS_REVIEWED_STATUS, 1d)
108 .expectedResult(50d);
109 new HierarchyTester(CoreMetrics.SECURITY_REVIEW_RATING)
110 .withValue(SECURITY_HOTSPOTS_REVIEWED, 100d)
111 .expectedRating(Rating.A);
113 new HierarchyTester(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED)
114 .withValue(NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1d)
115 .withValue(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, 1d)
116 .expectedResult(50d);
117 new HierarchyTester(CoreMetrics.NEW_SECURITY_REVIEW_RATING)
118 .withValue(NEW_SECURITY_HOTSPOTS_REVIEWED, 0d)
119 .expectedRating(Rating.E);
123 public void test_violations() {
124 withNoIssues().assertThatValueIs(CoreMetrics.VIOLATIONS, 0);
125 with(newGroup(), newGroup().setCount(4)).assertThatValueIs(CoreMetrics.VIOLATIONS, 5);
128 IssueGroupDto resolved = newResolvedGroup(Issue.RESOLUTION_FIXED, Issue.STATUS_RESOLVED);
129 with(newGroup(), newGroup(), resolved).assertThatValueIs(CoreMetrics.VIOLATIONS, 2);
131 // include issues on leak
132 IssueGroupDto onLeak = newGroup().setCount(11).setInLeak(true);
133 with(newGroup(), newGroup(), onLeak).assertThatValueIs(CoreMetrics.VIOLATIONS, 1 + 1 + 11);
137 public void test_bugs() {
138 withNoIssues().assertThatValueIs(CoreMetrics.BUGS, 0);
140 newGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setCount(3),
141 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setCount(5),
143 newResolvedGroup(RuleType.BUG).setCount(7),
145 newGroup(RuleType.CODE_SMELL).setCount(11))
146 .assertThatValueIs(CoreMetrics.BUGS, 3 + 5);
150 public void test_code_smells() {
151 withNoIssues().assertThatValueIs(CoreMetrics.CODE_SMELLS, 0);
153 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setCount(3),
154 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setCount(5),
156 newResolvedGroup(RuleType.CODE_SMELL).setCount(7),
158 newGroup(RuleType.BUG).setCount(11))
159 .assertThatValueIs(CoreMetrics.CODE_SMELLS, 3 + 5);
163 public void test_vulnerabilities() {
164 withNoIssues().assertThatValueIs(CoreMetrics.VULNERABILITIES, 0);
166 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MAJOR).setCount(3),
167 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.CRITICAL).setCount(5),
169 newResolvedGroup(RuleType.VULNERABILITY).setCount(7),
170 // not vulnerabilities
171 newGroup(RuleType.BUG).setCount(11))
172 .assertThatValueIs(CoreMetrics.VULNERABILITIES, 3 + 5);
176 public void test_security_hotspots() {
177 withNoIssues().assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS, 0);
179 newGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Severity.MAJOR).setCount(3),
180 newGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Severity.CRITICAL).setCount(5),
182 newResolvedGroup(RuleType.SECURITY_HOTSPOT).setCount(7),
184 newGroup(RuleType.BUG).setCount(11))
185 .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS, 3 + 5);
189 public void test_security_review_rating() {
191 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
192 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
193 .assertThatValueIs(SECURITY_REVIEW_RATING, Rating.B);
196 .assertThatValueIs(SECURITY_REVIEW_RATING, Rating.A);
200 public void test_security_hotspots_reviewed() {
202 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
203 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
204 .assertThatValueIs(SECURITY_HOTSPOTS_REVIEWED, 75.0);
207 .assertNoValue(SECURITY_HOTSPOTS_REVIEWED);
211 public void test_security_hotspots_reviewed_status() {
213 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
214 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
215 .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS, 3.0);
218 .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS, 0.0);
222 public void test_security_hotspots_to_review_status() {
224 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
225 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
226 .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1.0);
229 .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 0.0);
233 public void count_unresolved_by_severity() {
235 .assertThatValueIs(CoreMetrics.BLOCKER_VIOLATIONS, 0)
236 .assertThatValueIs(CoreMetrics.CRITICAL_VIOLATIONS, 0)
237 .assertThatValueIs(CoreMetrics.MAJOR_VIOLATIONS, 0)
238 .assertThatValueIs(CoreMetrics.MINOR_VIOLATIONS, 0)
239 .assertThatValueIs(CoreMetrics.INFO_VIOLATIONS, 0);
242 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MAJOR).setCount(3),
243 newGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setCount(5),
244 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setCount(7),
245 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setCount(11),
246 // exclude security hotspot
247 newGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Severity.CRITICAL).setCount(15),
249 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(true).setCount(13),
251 newResolvedGroup(RuleType.VULNERABILITY).setSeverity(Severity.INFO).setCount(17),
252 newResolvedGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setCount(19),
253 newResolvedGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Severity.INFO).setCount(21))
254 .assertThatValueIs(CoreMetrics.BLOCKER_VIOLATIONS, 11 + 13)
255 .assertThatValueIs(CoreMetrics.CRITICAL_VIOLATIONS, 7)
256 .assertThatValueIs(CoreMetrics.MAJOR_VIOLATIONS, 3 + 5)
257 .assertThatValueIs(CoreMetrics.MINOR_VIOLATIONS, 0)
258 .assertThatValueIs(CoreMetrics.INFO_VIOLATIONS, 0);
262 public void count_resolved() {
264 .assertThatValueIs(CoreMetrics.FALSE_POSITIVE_ISSUES, 0)
265 .assertThatValueIs(CoreMetrics.WONT_FIX_ISSUES, 0);
268 newResolvedGroup(Issue.RESOLUTION_FIXED, Issue.STATUS_RESOLVED).setCount(3),
269 newResolvedGroup(Issue.RESOLUTION_FALSE_POSITIVE, Issue.STATUS_CLOSED).setCount(5),
270 newResolvedGroup(Issue.RESOLUTION_WONT_FIX, Issue.STATUS_CLOSED).setSeverity(Severity.MAJOR).setCount(7),
271 newResolvedGroup(Issue.RESOLUTION_WONT_FIX, Issue.STATUS_CLOSED).setSeverity(Severity.BLOCKER).setCount(11),
272 newResolvedGroup(Issue.RESOLUTION_REMOVED, Issue.STATUS_CLOSED).setCount(13),
273 // exclude security hotspot
274 newResolvedGroup(Issue.RESOLUTION_WONT_FIX, Issue.STATUS_RESOLVED).setCount(15).setRuleType(RuleType.SECURITY_HOTSPOT.getDbConstant()),
275 // exclude unresolved
276 newGroup(RuleType.VULNERABILITY).setCount(17),
277 newGroup(RuleType.BUG).setCount(19))
278 .assertThatValueIs(CoreMetrics.FALSE_POSITIVE_ISSUES, 5)
279 .assertThatValueIs(CoreMetrics.WONT_FIX_ISSUES, 7 + 11);
283 public void count_by_status() {
285 .assertThatValueIs(CoreMetrics.CONFIRMED_ISSUES, 0)
286 .assertThatValueIs(CoreMetrics.OPEN_ISSUES, 0)
287 .assertThatValueIs(CoreMetrics.REOPENED_ISSUES, 0);
290 newGroup().setStatus(Issue.STATUS_CONFIRMED).setSeverity(Severity.BLOCKER).setCount(3),
291 newGroup().setStatus(Issue.STATUS_CONFIRMED).setSeverity(Severity.INFO).setCount(5),
292 newGroup().setStatus(Issue.STATUS_REOPENED).setCount(7),
293 newGroup(RuleType.CODE_SMELL).setStatus(Issue.STATUS_OPEN).setCount(9),
294 newGroup(RuleType.BUG).setStatus(Issue.STATUS_OPEN).setCount(11),
295 // exclude security hotspot
296 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_OPEN).setCount(12),
297 newResolvedGroup(Issue.RESOLUTION_FALSE_POSITIVE, Issue.STATUS_CLOSED).setCount(13))
298 .assertThatValueIs(CoreMetrics.CONFIRMED_ISSUES, 3 + 5)
299 .assertThatValueIs(CoreMetrics.OPEN_ISSUES, 9 + 11)
300 .assertThatValueIs(CoreMetrics.REOPENED_ISSUES, 7);
304 public void test_technical_debt() {
305 withNoIssues().assertThatValueIs(CoreMetrics.TECHNICAL_DEBT, 0);
308 newGroup(RuleType.CODE_SMELL).setEffort(3.0).setInLeak(false),
309 newGroup(RuleType.CODE_SMELL).setEffort(5.0).setInLeak(true),
310 // exclude security hotspot
311 newGroup(RuleType.SECURITY_HOTSPOT).setEffort(9).setInLeak(true),
312 newGroup(RuleType.SECURITY_HOTSPOT).setEffort(11).setInLeak(false),
314 newGroup(RuleType.BUG).setEffort(7.0),
316 newResolvedGroup(RuleType.CODE_SMELL).setEffort(17.0))
317 .assertThatValueIs(CoreMetrics.TECHNICAL_DEBT, 3.0 + 5.0);
321 public void test_reliability_remediation_effort() {
322 withNoIssues().assertThatValueIs(CoreMetrics.RELIABILITY_REMEDIATION_EFFORT, 0);
325 newGroup(RuleType.BUG).setEffort(3.0),
326 newGroup(RuleType.BUG).setEffort(5.0).setSeverity(Severity.BLOCKER),
328 newGroup(RuleType.CODE_SMELL).setEffort(7.0),
330 newResolvedGroup(RuleType.BUG).setEffort(17.0))
331 .assertThatValueIs(CoreMetrics.RELIABILITY_REMEDIATION_EFFORT, 3.0 + 5.0);
335 public void test_security_remediation_effort() {
336 withNoIssues().assertThatValueIs(CoreMetrics.SECURITY_REMEDIATION_EFFORT, 0);
339 newGroup(RuleType.VULNERABILITY).setEffort(3.0),
340 newGroup(RuleType.VULNERABILITY).setEffort(5.0).setSeverity(Severity.BLOCKER),
342 newGroup(RuleType.CODE_SMELL).setEffort(7.0),
344 newResolvedGroup(RuleType.VULNERABILITY).setEffort(17.0))
345 .assertThatValueIs(CoreMetrics.SECURITY_REMEDIATION_EFFORT, 3.0 + 5.0);
349 public void test_sqale_debt_ratio_and_sqale_rating() {
351 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
352 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
354 // technical_debt not computed
355 with(CoreMetrics.DEVELOPMENT_COST, "0")
356 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
357 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
358 with(CoreMetrics.DEVELOPMENT_COST, "20")
359 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
360 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
362 // development_cost not computed
363 with(CoreMetrics.TECHNICAL_DEBT, 0)
364 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
365 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
366 with(CoreMetrics.TECHNICAL_DEBT, 20)
367 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
368 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
370 // input measures are available
371 with(CoreMetrics.TECHNICAL_DEBT, 20.0)
372 .andText(CoreMetrics.DEVELOPMENT_COST, "0")
373 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
374 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
376 with(CoreMetrics.TECHNICAL_DEBT, 20.0)
377 .andText(CoreMetrics.DEVELOPMENT_COST, "160")
378 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 12.5)
379 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.C);
381 with(CoreMetrics.TECHNICAL_DEBT, 20.0)
382 .andText(CoreMetrics.DEVELOPMENT_COST, "10")
383 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 200.0)
384 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.E);
386 // A is 5% --> min debt is exactly 200*0.05=10
387 with(CoreMetrics.DEVELOPMENT_COST, "200")
388 .and(CoreMetrics.TECHNICAL_DEBT, 10.0)
389 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 5.0)
390 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
392 with(CoreMetrics.TECHNICAL_DEBT, 0.0)
393 .andText(CoreMetrics.DEVELOPMENT_COST, "0")
394 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
395 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
397 with(CoreMetrics.TECHNICAL_DEBT, 0.0)
398 .andText(CoreMetrics.DEVELOPMENT_COST, "80")
399 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0);
401 with(CoreMetrics.TECHNICAL_DEBT, -20.0)
402 .andText(CoreMetrics.DEVELOPMENT_COST, "0")
403 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
404 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
406 // bug, debt can't be negative
407 with(CoreMetrics.TECHNICAL_DEBT, -20.0)
408 .andText(CoreMetrics.DEVELOPMENT_COST, "80")
409 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
410 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
412 // bug, cost can't be negative
413 with(CoreMetrics.TECHNICAL_DEBT, 20.0)
414 .andText(CoreMetrics.DEVELOPMENT_COST, "-80")
415 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
416 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
420 public void test_effort_to_reach_maintainability_rating_A() {
422 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
424 // technical_debt not computed
425 with(CoreMetrics.DEVELOPMENT_COST, 0.0)
426 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
427 with(CoreMetrics.DEVELOPMENT_COST, 20.0)
428 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
430 // development_cost not computed
431 with(CoreMetrics.TECHNICAL_DEBT, 0.0)
432 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
433 with(CoreMetrics.TECHNICAL_DEBT, 20.0)
434 // development cost is considered as zero, so the effort is to reach... zero
435 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 20.0);
438 with(CoreMetrics.DEVELOPMENT_COST, "200")
439 .and(CoreMetrics.TECHNICAL_DEBT, 40.0)
440 // B is 5% --> goal is to reach 200*0.05=10 --> effort is 40-10=30
441 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 40.0 - (200.0 * 0.05));
444 with(CoreMetrics.DEVELOPMENT_COST, "200")
445 .and(CoreMetrics.TECHNICAL_DEBT, 180.0)
446 // B is 5% --> goal is to reach 200*0.05=10 --> effort is 180-10=170
447 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 180.0 - (200.0 * 0.05));
450 with(CoreMetrics.DEVELOPMENT_COST, "200")
451 .and(CoreMetrics.TECHNICAL_DEBT, 8.0)
452 // B is 5% --> goal is to reach 200*0.05=10 --> debt is already at 8 --> effort to reach A is zero
453 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
455 // exactly lower range of B
456 with(CoreMetrics.DEVELOPMENT_COST, "200")
457 .and(CoreMetrics.TECHNICAL_DEBT, 10.0)
458 // B is 5% --> goal is to reach 200*0.05=10 --> debt is 10 --> effort to reach A is zero
459 // FIXME need zero to reach A but effective rating is B !
460 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
464 public void test_reliability_rating() {
466 .assertThatValueIs(CoreMetrics.RELIABILITY_RATING, Rating.A);
469 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setCount(1),
470 newGroup(RuleType.BUG).setSeverity(Severity.MINOR).setCount(5),
471 // excluded, not a bug
472 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setCount(3))
473 // highest severity of bugs is CRITICAL --> D
474 .assertThatValueIs(CoreMetrics.RELIABILITY_RATING, Rating.D);
477 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setCount(3),
478 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.CRITICAL).setCount(5))
480 .assertThatValueIs(CoreMetrics.RELIABILITY_RATING, Rating.A);
484 public void test_security_rating() {
486 .assertThatValueIs(CoreMetrics.SECURITY_RATING, Rating.A);
489 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.CRITICAL).setCount(1),
490 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MINOR).setCount(5),
491 // excluded, not a vulnerability
492 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setCount(3))
493 // highest severity of vulnerabilities is CRITICAL --> D
494 .assertThatValueIs(CoreMetrics.SECURITY_RATING, Rating.D);
497 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setCount(3),
498 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setCount(5))
499 // no vulnerabilities --> A
500 .assertThatValueIs(CoreMetrics.SECURITY_RATING, Rating.A);
504 public void test_new_bugs() {
505 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_BUGS, 0.0);
508 newGroup(RuleType.BUG).setInLeak(false).setSeverity(Severity.MAJOR).setCount(3),
509 newGroup(RuleType.BUG).setInLeak(true).setSeverity(Severity.CRITICAL).setCount(5),
510 newGroup(RuleType.BUG).setInLeak(true).setSeverity(Severity.MINOR).setCount(7),
512 newGroup(RuleType.CODE_SMELL).setInLeak(true).setCount(9),
513 newGroup(RuleType.VULNERABILITY).setInLeak(true).setCount(11))
514 .assertThatLeakValueIs(CoreMetrics.NEW_BUGS, 5 + 7);
519 public void test_new_code_smells() {
520 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_CODE_SMELLS, 0.0);
523 newGroup(RuleType.CODE_SMELL).setInLeak(false).setSeverity(Severity.MAJOR).setCount(3),
524 newGroup(RuleType.CODE_SMELL).setInLeak(true).setSeverity(Severity.CRITICAL).setCount(5),
525 newGroup(RuleType.CODE_SMELL).setInLeak(true).setSeverity(Severity.MINOR).setCount(7),
527 newGroup(RuleType.BUG).setInLeak(true).setCount(9),
528 newGroup(RuleType.VULNERABILITY).setInLeak(true).setCount(11))
529 .assertThatLeakValueIs(CoreMetrics.NEW_CODE_SMELLS, 5 + 7);
533 public void test_new_vulnerabilities() {
534 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_VULNERABILITIES, 0.0);
537 newGroup(RuleType.VULNERABILITY).setInLeak(false).setSeverity(Severity.MAJOR).setCount(3),
538 newGroup(RuleType.VULNERABILITY).setInLeak(true).setSeverity(Severity.CRITICAL).setCount(5),
539 newGroup(RuleType.VULNERABILITY).setInLeak(true).setSeverity(Severity.MINOR).setCount(7),
540 // not vulnerabilities
541 newGroup(RuleType.BUG).setInLeak(true).setCount(9),
542 newGroup(RuleType.CODE_SMELL).setInLeak(true).setCount(11))
543 .assertThatLeakValueIs(CoreMetrics.NEW_VULNERABILITIES, 5 + 7);
547 public void test_new_security_hotspots() {
548 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS, 0.0);
551 newGroup(RuleType.SECURITY_HOTSPOT).setInLeak(false).setSeverity(Severity.MAJOR).setCount(3),
552 newGroup(RuleType.SECURITY_HOTSPOT).setInLeak(true).setSeverity(Severity.CRITICAL).setCount(5),
553 newGroup(RuleType.SECURITY_HOTSPOT).setInLeak(true).setSeverity(Severity.MINOR).setCount(7),
555 newGroup(RuleType.BUG).setInLeak(true).setCount(9),
556 newGroup(RuleType.CODE_SMELL).setInLeak(true).setCount(11))
557 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS, 5 + 7);
561 public void test_new_violations() {
562 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_VIOLATIONS, 0.0);
565 newGroup(RuleType.BUG).setInLeak(true).setCount(5),
566 newGroup(RuleType.CODE_SMELL).setInLeak(true).setCount(7),
567 newGroup(RuleType.VULNERABILITY).setInLeak(true).setCount(9),
569 newGroup(RuleType.BUG).setInLeak(false).setCount(11),
570 newGroup(RuleType.CODE_SMELL).setInLeak(false).setCount(13),
571 newGroup(RuleType.VULNERABILITY).setInLeak(false).setCount(17))
572 .assertThatLeakValueIs(CoreMetrics.NEW_VIOLATIONS, 5 + 7 + 9);
576 public void test_new_blocker_violations() {
578 .assertThatLeakValueIs(CoreMetrics.NEW_BLOCKER_VIOLATIONS, 0.0);
581 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(true).setCount(3),
582 newGroup(RuleType.BUG).setSeverity(Severity.BLOCKER).setInLeak(true).setCount(5),
583 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.BLOCKER).setInLeak(true).setCount(7),
585 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(9),
587 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(false).setCount(11),
588 newGroup(RuleType.BUG).setSeverity(Severity.BLOCKER).setInLeak(false).setCount(13))
589 .assertThatLeakValueIs(CoreMetrics.NEW_BLOCKER_VIOLATIONS, 3 + 5 + 7);
593 public void test_new_critical_violations() {
595 .assertThatLeakValueIs(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 0.0);
598 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(3),
599 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(5),
600 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(7),
602 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setInLeak(true).setCount(9),
604 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(false).setCount(11),
605 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setInLeak(false).setCount(13))
606 .assertThatLeakValueIs(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 3 + 5 + 7);
610 public void test_new_major_violations() {
612 .assertThatLeakValueIs(CoreMetrics.NEW_MAJOR_VIOLATIONS, 0.0);
615 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setInLeak(true).setCount(3),
616 newGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setInLeak(true).setCount(5),
617 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MAJOR).setInLeak(true).setCount(7),
619 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(9),
621 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setInLeak(false).setCount(11),
622 newGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setInLeak(false).setCount(13))
623 .assertThatLeakValueIs(CoreMetrics.NEW_MAJOR_VIOLATIONS, 3 + 5 + 7);
627 public void test_new_minor_violations() {
629 .assertThatLeakValueIs(CoreMetrics.NEW_MINOR_VIOLATIONS, 0.0);
632 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MINOR).setInLeak(true).setCount(3),
633 newGroup(RuleType.BUG).setSeverity(Severity.MINOR).setInLeak(true).setCount(5),
634 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MINOR).setInLeak(true).setCount(7),
636 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(9),
638 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MINOR).setInLeak(false).setCount(11),
639 newGroup(RuleType.BUG).setSeverity(Severity.MINOR).setInLeak(false).setCount(13))
640 .assertThatLeakValueIs(CoreMetrics.NEW_MINOR_VIOLATIONS, 3 + 5 + 7);
644 public void test_new_info_violations() {
646 .assertThatLeakValueIs(CoreMetrics.NEW_INFO_VIOLATIONS, 0.0);
649 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.INFO).setInLeak(true).setCount(3),
650 newGroup(RuleType.BUG).setSeverity(Severity.INFO).setInLeak(true).setCount(5),
651 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.INFO).setInLeak(true).setCount(7),
653 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(9),
655 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.INFO).setInLeak(false).setCount(11),
656 newGroup(RuleType.BUG).setSeverity(Severity.INFO).setInLeak(false).setCount(13))
657 .assertThatLeakValueIs(CoreMetrics.NEW_INFO_VIOLATIONS, 3 + 5 + 7);
661 public void test_new_technical_debt() {
662 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0);
665 newGroup(RuleType.CODE_SMELL).setEffort(3.0).setInLeak(true),
667 newGroup(RuleType.CODE_SMELL).setEffort(5.0).setInLeak(false),
669 newGroup(RuleType.SECURITY_HOTSPOT).setEffort(9.0).setInLeak(true),
670 newGroup(RuleType.BUG).setEffort(7.0).setInLeak(true),
672 newResolvedGroup(RuleType.CODE_SMELL).setEffort(17.0).setInLeak(true))
673 .assertThatLeakValueIs(CoreMetrics.NEW_TECHNICAL_DEBT, 3.0);
677 public void test_new_reliability_remediation_effort() {
678 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_RELIABILITY_REMEDIATION_EFFORT, 0.0);
681 newGroup(RuleType.BUG).setEffort(3.0).setInLeak(true),
683 newGroup(RuleType.BUG).setEffort(5.0).setInLeak(false),
685 newGroup(RuleType.CODE_SMELL).setEffort(7.0).setInLeak(true),
687 newResolvedGroup(RuleType.BUG).setEffort(17.0).setInLeak(true))
688 .assertThatLeakValueIs(CoreMetrics.NEW_RELIABILITY_REMEDIATION_EFFORT, 3.0);
692 public void test_new_security_remediation_effort() {
693 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_REMEDIATION_EFFORT, 0.0);
696 newGroup(RuleType.VULNERABILITY).setEffort(3.0).setInLeak(true),
698 newGroup(RuleType.VULNERABILITY).setEffort(5.0).setInLeak(false),
700 newGroup(RuleType.CODE_SMELL).setEffort(7.0).setInLeak(true),
702 newResolvedGroup(RuleType.VULNERABILITY).setEffort(17.0).setInLeak(true))
703 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_REMEDIATION_EFFORT, 3.0);
707 public void test_new_reliability_rating() {
708 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_RELIABILITY_RATING, Rating.A);
711 newGroup(RuleType.BUG).setSeverity(Severity.INFO).setCount(3).setInLeak(true),
712 newGroup(RuleType.BUG).setSeverity(Severity.MINOR).setCount(1).setInLeak(true),
714 newGroup(RuleType.BUG).setSeverity(Severity.BLOCKER).setInLeak(false),
716 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(true),
718 newResolvedGroup(RuleType.BUG).setSeverity(Severity.BLOCKER).setInLeak(true))
719 // highest severity of bugs on leak period is minor -> B
720 .assertThatLeakValueIs(CoreMetrics.NEW_RELIABILITY_RATING, Rating.B);
724 public void test_new_security_rating() {
725 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_RATING, Rating.A);
728 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.INFO).setCount(3).setInLeak(true),
729 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MINOR).setCount(1).setInLeak(true),
731 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.BLOCKER).setInLeak(false),
733 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(true),
735 newResolvedGroup(RuleType.VULNERABILITY).setSeverity(Severity.BLOCKER).setInLeak(true))
736 // highest severity of bugs on leak period is minor -> B
737 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_RATING, Rating.B);
741 public void test_new_security_review_rating() {
743 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3).setInLeak(true),
744 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
746 newGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Issue.STATUS_TO_REVIEW).setInLeak(false))
747 .assertThatLeakValueIs(NEW_SECURITY_REVIEW_RATING, Rating.B);
750 .assertThatLeakValueIs(NEW_SECURITY_REVIEW_RATING, Rating.A);
754 public void test_new_security_hotspots_reviewed() {
756 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3).setInLeak(true),
757 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
759 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(5).setInLeak(false))
760 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED, 75.0);
763 .assertNoLeakValue(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED);
767 public void test_new_security_hotspots_reviewed_status() {
769 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3).setInLeak(true),
770 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
772 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(5).setInLeak(false))
773 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, 3.0);
776 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, 0.0);
780 public void test_new_security_hotspots_to_review_status() {
782 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3).setInLeak(true),
783 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
785 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(5).setInLeak(false))
786 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1.0);
789 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 0.0);
793 public void test_new_sqale_debt_ratio_and_new_maintainability_rating() {
795 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
796 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
798 // technical_debt not computed
799 withLeak(CoreMetrics.NEW_DEVELOPMENT_COST, 0)
800 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
801 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
802 withLeak(CoreMetrics.NEW_DEVELOPMENT_COST, 20)
803 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
804 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
806 // development_cost not computed
807 withLeak(CoreMetrics.NEW_TECHNICAL_DEBT, 0)
808 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
809 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
810 withLeak(CoreMetrics.NEW_TECHNICAL_DEBT, 20)
811 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
812 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
814 // input measures are available
815 withLeak(CoreMetrics.NEW_TECHNICAL_DEBT, 20.0)
816 .andLeak(CoreMetrics.NEW_DEVELOPMENT_COST, 0.0)
817 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
818 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
820 withLeak(CoreMetrics.NEW_TECHNICAL_DEBT, 20.0)
821 .andText(CoreMetrics.NEW_DEVELOPMENT_COST, "160")
822 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 12.5)
823 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.C);
825 withLeak(CoreMetrics.NEW_TECHNICAL_DEBT, 20.0)
826 .andText(CoreMetrics.NEW_DEVELOPMENT_COST, "10")
827 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 200.0)
828 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.E);
830 // A is 5% --> min debt is exactly 200*0.05=10
831 with(CoreMetrics.NEW_DEVELOPMENT_COST, "200")
832 .andLeak(CoreMetrics.NEW_TECHNICAL_DEBT, 10.0)
833 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 5.0)
834 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
836 withLeak(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0)
837 .andText(CoreMetrics.NEW_DEVELOPMENT_COST, "0")
838 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
839 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
841 withLeak(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0)
842 .andText(CoreMetrics.NEW_DEVELOPMENT_COST, "80")
843 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0);
845 withLeak(CoreMetrics.NEW_TECHNICAL_DEBT, -20.0)
846 .andText(CoreMetrics.NEW_DEVELOPMENT_COST, "0")
847 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
848 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
850 // bug, debt can't be negative
851 withLeak(CoreMetrics.NEW_TECHNICAL_DEBT, -20.0)
852 .andText(CoreMetrics.NEW_DEVELOPMENT_COST, "80")
853 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
854 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
856 // bug, cost can't be negative
857 withLeak(CoreMetrics.NEW_TECHNICAL_DEBT, 20.0)
858 .andText(CoreMetrics.NEW_DEVELOPMENT_COST, "-80")
859 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
860 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
863 private Verifier with(IssueGroupDto... groups) {
864 return new Verifier(groups);
867 private Verifier withNoIssues() {
868 return new Verifier(new IssueGroupDto[0]);
871 private Verifier with(Metric metric, double value) {
872 return new Verifier(new IssueGroupDto[0]).and(metric, value);
875 private Verifier with(Metric metric, String value) {
876 return new Verifier(new IssueGroupDto[0]).andText(metric, value);
879 private Verifier withLeak(Metric metric, double leakValue) {
880 return new Verifier(new IssueGroupDto[0]).andLeak(metric, leakValue);
883 private class Verifier {
884 private final IssueGroupDto[] groups;
885 private final InitialValues initialValues = new InitialValues();
887 private Verifier(IssueGroupDto[] groups) {
888 this.groups = groups;
891 Verifier and(Metric metric, double value) {
892 this.initialValues.values.put(metric, value);
896 Verifier andLeak(Metric metric, double value) {
897 this.initialValues.leakValues.put(metric, value);
901 Verifier andText(Metric metric, String value) {
902 this.initialValues.text.put(metric, value);
906 Verifier assertThatValueIs(Metric metric, double expectedValue) {
907 TestContext context = run(metric, false);
908 assertThat(context.doubleValue).isNotNull().isEqualTo(expectedValue);
912 Verifier assertThatLeakValueIs(Metric metric, double expectedValue) {
913 TestContext context = run(metric, true);
914 assertThat(context.doubleLeakValue).isNotNull().isEqualTo(expectedValue);
918 Verifier assertThatLeakValueIs(Metric metric, Rating expectedRating) {
919 TestContext context = run(metric, true);
920 assertThat(context.ratingLeakValue).isNotNull().isEqualTo(expectedRating);
924 Verifier assertNoLeakValue(Metric metric) {
925 TestContext context = run(metric, true);
926 assertThat(context.ratingLeakValue).isNull();
930 Verifier assertThatValueIs(Metric metric, Rating expectedValue) {
931 TestContext context = run(metric, false);
932 assertThat(context.ratingValue).isNotNull().isEqualTo(expectedValue);
936 Verifier assertNoValue(Metric metric) {
937 TestContext context = run(metric, false);
938 assertThat(context.ratingValue).isNull();
942 private TestContext run(Metric metric, boolean expectLeakFormula) {
943 MeasureUpdateFormula formula = underTest.getFormulas().stream()
944 .filter(f -> f.getMetric().getKey().equals(metric.getKey()))
947 assertThat(formula.isOnLeak()).isEqualTo(expectLeakFormula);
948 TestContext context = new TestContext(formula.getDependentMetrics(), initialValues);
949 formula.compute(context, newIssueCounter(groups));
954 private static IssueCounter newIssueCounter(IssueGroupDto... issues) {
955 return new IssueCounter(asList(issues));
958 private static IssueGroupDto newGroup() {
959 return newGroup(RuleType.CODE_SMELL);
962 private static IssueGroupDto newGroup(RuleType ruleType) {
963 IssueGroupDto dto = new IssueGroupDto();
964 // set non-null fields
965 dto.setRuleType(ruleType.getDbConstant());
968 dto.setSeverity(Severity.INFO);
969 dto.setStatus(Issue.STATUS_OPEN);
970 dto.setInLeak(false);
974 private static IssueGroupDto newResolvedGroup(RuleType ruleType) {
975 return newGroup(ruleType).setResolution(Issue.RESOLUTION_FALSE_POSITIVE).setStatus(Issue.STATUS_CLOSED);
978 private static IssueGroupDto newResolvedGroup(String resolution, String status) {
979 return newGroup().setResolution(resolution).setStatus(status);
982 private static class TestContext implements MeasureUpdateFormula.Context {
983 private final Set<Metric> dependentMetrics;
984 private final InitialValues initialValues;
985 private Double doubleValue;
986 private Rating ratingValue;
987 private Double doubleLeakValue;
988 private Rating ratingLeakValue;
990 private TestContext(Collection<Metric> dependentMetrics, InitialValues initialValues) {
991 this.dependentMetrics = new HashSet<>(dependentMetrics);
992 this.initialValues = initialValues;
995 @Override public List<Double> getChildrenValues() {
996 return initialValues.childrenValues;
999 @Override public List<Double> getChildrenLeakValues() {
1000 return initialValues.childrenLeakValues;
1004 public ComponentDto getComponent() {
1005 throw new UnsupportedOperationException();
1009 public DebtRatingGrid getDebtRatingGrid() {
1010 return new DebtRatingGrid(new double[] {0.05, 0.1, 0.2, 0.5});
1014 public Optional<Double> getValue(Metric metric) {
1015 if (!dependentMetrics.contains(metric)) {
1016 throw new IllegalStateException("Metric " + metric.getKey() + " is not declared as a dependency");
1018 if (initialValues.values.containsKey(metric)) {
1019 return Optional.of(initialValues.values.get(metric));
1021 return Optional.empty();
1025 public Optional<String> getText(Metric metric) {
1026 if (initialValues.text.containsKey(metric)) {
1027 return Optional.of(initialValues.text.get(metric));
1029 return Optional.empty();
1033 public Optional<Double> getLeakValue(Metric metric) {
1034 if (!dependentMetrics.contains(metric)) {
1035 throw new IllegalStateException("Metric " + metric.getKey() + " is not declared as a dependency");
1037 if (initialValues.leakValues.containsKey(metric)) {
1038 return Optional.of(initialValues.leakValues.get(metric));
1040 return Optional.empty();
1044 public void setValue(double value) {
1045 this.doubleValue = value;
1049 public void setValue(Rating value) {
1050 this.ratingValue = value;
1054 public void setLeakValue(double value) {
1055 this.doubleLeakValue = value;
1059 public void setLeakValue(Rating value) {
1060 this.ratingLeakValue = value;
1064 private class InitialValues {
1065 private final Map<Metric, Double> values = new HashMap<>();
1066 private final Map<Metric, Double> leakValues = new HashMap<>();
1067 private final List<Double> childrenValues = new ArrayList<>();
1068 private final List<Double> childrenLeakValues = new ArrayList<>();
1069 private final Map<Metric, String> text = new HashMap<>();
1072 private class HierarchyTester {
1073 private final Metric metric;
1074 private final InitialValues initialValues;
1075 private final MeasureUpdateFormula formula;
1077 public HierarchyTester(Metric metric) {
1078 this.metric = metric;
1079 this.initialValues = new InitialValues();
1080 this.formula = underTest.getFormulas().stream().filter(f -> f.getMetric().equals(metric)).findAny().get();
1083 public HierarchyTester withValue(Metric metric, Double value) {
1084 if (formula.isOnLeak()) {
1085 this.initialValues.leakValues.put(metric, value);
1087 this.initialValues.values.put(metric, value);
1092 public HierarchyTester withValue(Double value) {
1093 return withValue(metric, value);
1096 public HierarchyTester withChildrenValues(Double... values) {
1097 if (formula.isOnLeak()) {
1098 this.initialValues.childrenLeakValues.addAll(asList(values));
1100 this.initialValues.childrenValues.addAll(asList(values));
1105 public HierarchyTester expectedResult(@Nullable Double expected) {
1106 TestContext ctx = run();
1107 if (formula.isOnLeak()) {
1108 assertThat(ctx.doubleLeakValue).isEqualTo(expected);
1110 assertThat(ctx.doubleValue).isEqualTo(expected);
1115 public HierarchyTester expectedRating(@Nullable Rating rating) {
1116 TestContext ctx = run();
1117 if (formula.isOnLeak()) {
1118 assertThat(ctx.ratingLeakValue).isEqualTo(rating);
1120 assertThat(ctx.ratingValue).isEqualTo(rating);
1125 private TestContext run() {
1126 List<Metric> deps = new LinkedList<>(formula.getDependentMetrics());
1127 deps.add(formula.getMetric());
1128 deps.addAll(initialValues.values.keySet());
1129 deps.addAll(initialValues.leakValues.keySet());
1130 deps.addAll(initialValues.text.keySet());
1131 TestContext context = new TestContext(deps, initialValues);
1132 formula.computeHierarchy(context);