3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.ce.task.projectanalysis.qualitymodel;
22 import com.google.common.collect.ImmutableMap;
23 import com.google.common.collect.ImmutableSet;
24 import com.google.common.collect.Ordering;
25 import java.util.Arrays;
26 import java.util.HashSet;
27 import java.util.Optional;
29 import java.util.stream.Stream;
30 import org.assertj.core.data.Offset;
31 import org.junit.jupiter.api.BeforeEach;
32 import org.junit.jupiter.api.Test;
33 import org.junit.jupiter.api.extension.RegisterExtension;
34 import org.junit.jupiter.params.ParameterizedTest;
35 import org.junit.jupiter.params.provider.Arguments;
36 import org.junit.jupiter.params.provider.MethodSource;
37 import org.sonar.api.utils.KeyValueFormat;
38 import org.sonar.ce.task.projectanalysis.component.Component;
39 import org.sonar.ce.task.projectanalysis.component.FileAttributes;
40 import org.sonar.ce.task.projectanalysis.component.ReportComponent;
41 import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
42 import org.sonar.ce.task.projectanalysis.component.VisitorsCrawler;
43 import org.sonar.ce.task.projectanalysis.measure.Measure;
44 import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
45 import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
46 import org.sonar.ce.task.projectanalysis.source.NewLinesRepository;
47 import org.sonar.server.measure.DebtRatingGrid;
48 import org.sonar.server.measure.Rating;
50 import static com.google.common.base.Preconditions.checkArgument;
51 import static org.junit.jupiter.params.provider.Arguments.arguments;
52 import static org.mockito.Mockito.mock;
53 import static org.mockito.Mockito.when;
54 import static org.sonar.api.measures.CoreMetrics.NCLOC_DATA;
55 import static org.sonar.api.measures.CoreMetrics.NCLOC_DATA_KEY;
56 import static org.sonar.api.measures.CoreMetrics.NEW_DEVELOPMENT_COST;
57 import static org.sonar.api.measures.CoreMetrics.NEW_DEVELOPMENT_COST_KEY;
58 import static org.sonar.api.measures.CoreMetrics.NEW_MAINTAINABILITY_RATING;
59 import static org.sonar.api.measures.CoreMetrics.NEW_MAINTAINABILITY_RATING_KEY;
60 import static org.sonar.api.measures.CoreMetrics.NEW_SQALE_DEBT_RATIO;
61 import static org.sonar.api.measures.CoreMetrics.NEW_SQALE_DEBT_RATIO_KEY;
62 import static org.sonar.api.measures.CoreMetrics.NEW_TECHNICAL_DEBT;
63 import static org.sonar.api.measures.CoreMetrics.NEW_TECHNICAL_DEBT_KEY;
64 import static org.sonar.ce.task.projectanalysis.component.Component.Type.DIRECTORY;
65 import static org.sonar.ce.task.projectanalysis.component.Component.Type.FILE;
66 import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT;
67 import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;
68 import static org.sonar.ce.task.projectanalysis.measure.MeasureAssert.assertThat;
69 import static org.sonar.server.measure.Rating.A;
70 import static org.sonar.server.measure.Rating.D;
71 import static org.sonar.server.measure.Rating.E;
72 import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO;
73 import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY;
74 import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING;
75 import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY;
76 import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT;
77 import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY;
79 public class NewMaintainabilityMeasuresVisitorTest {
81 private static final double[] RATING_GRID = new double[] {0.1, 0.2, 0.5, 1};
83 private static final String LANGUAGE_1_KEY = "language 1 key";
84 private static final long DEV_COST = 30L;
85 private static final int ROOT_REF = 1;
86 private static final int LANGUAGE_1_FILE_REF = 11111;
87 private static final Offset<Double> VALUE_COMPARISON_OFFSET = Offset.offset(0.01);
90 public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
92 public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
93 .add(NEW_TECHNICAL_DEBT)
95 .add(NEW_SQALE_DEBT_RATIO)
96 .add(NEW_MAINTAINABILITY_RATING)
97 .add(NEW_DEVELOPMENT_COST)
98 .add(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT)
99 .add(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO)
100 .add(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING);
103 public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
105 private NewLinesRepository newLinesRepository = mock(NewLinesRepository.class);
106 private RatingSettings ratingSettings = mock(RatingSettings.class);
108 private VisitorsCrawler underTest;
111 public void setUp() {
112 when(ratingSettings.getDebtRatingGrid()).thenReturn(new DebtRatingGrid(RATING_GRID));
113 when(ratingSettings.getDevCost()).thenReturn(DEV_COST);
114 underTest = new VisitorsCrawler(Arrays.asList(new NewMaintainabilityMeasuresVisitor(metricRepository, measureRepository, newLinesRepository, ratingSettings)));
117 private static Stream<Arguments> metrics() {
119 arguments(NEW_TECHNICAL_DEBT_KEY, NEW_SQALE_DEBT_RATIO_KEY, NEW_MAINTAINABILITY_RATING_KEY),
120 arguments(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY, NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY, NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY));
124 @MethodSource("metrics")
125 void project_has_new_measures(String remediationEffortKey, String debtRatioKey, String ratingKey) {
126 when(newLinesRepository.newLinesAvailable()).thenReturn(true);
127 treeRootHolder.setRoot(builder(PROJECT, ROOT_REF).build());
129 underTest.visit(treeRootHolder.getRoot());
131 assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 0);
132 assertNewRating(ratingKey, ROOT_REF, A);
136 @MethodSource("metrics")
137 void project_has_no_measure_if_new_lines_not_available(String remediationEffortKey, String debtRatioKey, String ratingKey) {
138 when(newLinesRepository.newLinesAvailable()).thenReturn(false);
139 treeRootHolder.setRoot(builder(PROJECT, ROOT_REF).build());
141 underTest.visit(treeRootHolder.getRoot());
143 assertNoNewDebtRatioMeasure(debtRatioKey, ROOT_REF);
144 assertNoNewMaintainability(ratingKey, ROOT_REF);
148 @MethodSource("metrics")
149 void file_has_no_new_debt_ratio_variation_if_new_lines_not_available(String remediationEffortKey, String debtRatioKey, String ratingKey) {
150 when(newLinesRepository.newLinesAvailable()).thenReturn(false);
151 setupOneFileAloneInAProject(remediationEffortKey,50, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.NO_NEW_LINES);
152 measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(50));
154 underTest.visit(treeRootHolder.getRoot());
156 assertNoNewDebtRatioMeasure(debtRatioKey, LANGUAGE_1_FILE_REF);
157 assertNoNewDebtRatioMeasure(debtRatioKey, ROOT_REF);
161 @MethodSource("metrics")
162 void file_has_0_new_debt_ratio_if_no_line_is_new(String remediationEffortKey, String debtRatioKey, String ratingKey) {
163 ReportComponent file = builder(FILE, LANGUAGE_1_FILE_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_1_KEY, 1)).build();
164 treeRootHolder.setRoot(
165 builder(PROJECT, ROOT_REF)
168 measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, remediationEffortKey, createNewDebtMeasure(50));
169 measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNclocDataMeasure(2, 3, 4));
172 underTest.visit(treeRootHolder.getRoot());
174 assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 0);
175 assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 0);
179 @MethodSource("metrics")
180 void file_has_new_debt_ratio_if_some_lines_are_new(String remediationEffortKey, String debtRatioKey, String ratingKey) {
181 when(newLinesRepository.newLinesAvailable()).thenReturn(true);
182 setupOneFileAloneInAProject(remediationEffortKey,50, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_NEW_LINES);
183 measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(50));
185 underTest.visit(treeRootHolder.getRoot());
187 assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 83.33);
188 assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 83.33);
192 @MethodSource("metrics")
193 void new_debt_ratio_changes_with_language_cost(String remediationEffortKey, String debtRatioKey, String ratingKey) {
194 when(ratingSettings.getDevCost()).thenReturn(DEV_COST * 10);
195 setupOneFileAloneInAProject(remediationEffortKey,50, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_NEW_LINES);
196 measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(50));
198 underTest.visit(treeRootHolder.getRoot());
200 assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 8.33);
201 assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 8.33);
205 @MethodSource("metrics")
206 void new_debt_ratio_changes_with_new_technical_debt(String remediationEffortKey, String debtRatioKey, String ratingKey) {
207 setupOneFileAloneInAProject(remediationEffortKey, 500, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_NEW_LINES);
208 measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(500));
210 underTest.visit(treeRootHolder.getRoot());
212 assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 833.33);
213 assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 833.33);
217 @MethodSource("metrics")
218 void new_debt_ratio_on_non_file_level_is_based_on_new_technical_debt_of_that_level(String remediationEffortKey, String debtRatioKey, String ratingKey) {
219 setupOneFileAloneInAProject(remediationEffortKey, 500, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_NEW_LINES);
220 measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(1200));
222 underTest.visit(treeRootHolder.getRoot());
224 assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 833.33);
225 assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 833.33);
229 @MethodSource("metrics")
230 void new_debt_ratio_when_file_is_unit_test(String remediationEffortKey, String debtRatioKey, String ratingKey) {
231 setupOneFileAloneInAProject(remediationEffortKey, 500, Flag.UT_FILE, Flag.WITH_NCLOC, Flag.WITH_NEW_LINES);
232 measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(1200));
234 underTest.visit(treeRootHolder.getRoot());
236 assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 833.33);
237 assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 833.33);
241 @MethodSource("metrics")
242 void new_debt_ratio_is_0_when_file_has_no_new_lines(String remediationEffortKey, String debtRatioKey, String ratingKey) {
243 when(newLinesRepository.newLinesAvailable()).thenReturn(true);
244 setupOneFileAloneInAProject(remediationEffortKey,50, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.NO_NEW_LINES);
245 measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(50));
247 underTest.visit(treeRootHolder.getRoot());
249 assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 0);
250 assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 0);
254 @MethodSource("metrics")
255 void new_debt_ratio_is_0_on_non_file_level_when_no_file_has_new_lines(String remediationEffortKey, String debtRatioKey, String ratingKey) {
256 when(newLinesRepository.newLinesAvailable()).thenReturn(true);
257 setupOneFileAloneInAProject(remediationEffortKey,50, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.NO_NEW_LINES);
258 measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(200));
260 underTest.visit(treeRootHolder.getRoot());
262 assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 0);
263 assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 0);
267 @MethodSource("metrics")
268 void new_debt_ratio_is_0_when_there_is_no_ncloc_in_file(String remediationEffortKey, String debtRatioKey, String ratingKey) {
269 setupOneFileAloneInAProject(remediationEffortKey, 50, Flag.SRC_FILE, Flag.NO_NCLOC, Flag.WITH_NEW_LINES);
270 measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(50));
272 underTest.visit(treeRootHolder.getRoot());
274 assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 0);
275 assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 0);
279 @MethodSource("metrics")
280 void new_debt_ratio_is_0_on_non_file_level_when_one_file_has_zero_new_debt_because_of_no_changeset(String remediationEffortKey, String debtRatioKey, String ratingKey) {
281 setupOneFileAloneInAProject(remediationEffortKey, 50, Flag.SRC_FILE, Flag.NO_NCLOC, Flag.WITH_NEW_LINES);
282 measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(200));
284 underTest.visit(treeRootHolder.getRoot());
286 assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 0);
287 assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 0);
291 @MethodSource("metrics")
292 void new_debt_ratio_is_0_when_ncloc_measure_is_missing(String remediationEffortKey, String debtRatioKey, String ratingKey) {
293 setupOneFileAloneInAProject(remediationEffortKey, 50, Flag.SRC_FILE, Flag.MISSING_MEASURE_NCLOC, Flag.WITH_NEW_LINES);
294 measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(50));
296 underTest.visit(treeRootHolder.getRoot());
298 assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 0);
299 assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 0);
303 @MethodSource("metrics")
304 void leaf_components_always_have_a_measure_when_at_least_one_period_exist_and_ratio_is_computed_from_current_level_new_debt(String remediationEffortKey, String debtRatioKey,
306 Component file = builder(FILE, LANGUAGE_1_FILE_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_1_KEY, 1)).build();
307 treeRootHolder.setRoot(
308 builder(PROJECT, ROOT_REF)
310 builder(DIRECTORY, 111)
315 Measure newDebtMeasure = createNewDebtMeasure(50);
316 measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, remediationEffortKey, newDebtMeasure);
317 measureRepository.addRawMeasure(111, remediationEffortKey, createNewDebtMeasure(150));
318 measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(250));
319 // 4 lines file, only first one is not ncloc
320 measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNclocDataMeasure(2, 3, 4));
321 // first 2 lines are before all snapshots, 2 last lines are after PERIOD 2's snapshot date
322 setNewLines(file, 3, 4);
323 underTest.visit(treeRootHolder.getRoot());
325 assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 83.33);
326 assertNewDebtRatioValues(debtRatioKey, 111, 83.33);
327 assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 83.33);
331 @MethodSource("metrics")
332 void compute_new_maintainability_rating(String remediationEffortKey, String debtRatioKey, String ratingKey) {
333 ReportComponent file = builder(FILE, LANGUAGE_1_FILE_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_1_KEY, 1)).build();
334 treeRootHolder.setRoot(
335 builder(PROJECT, ROOT_REF)
337 builder(DIRECTORY, 111)
342 Measure newDebtMeasure = createNewDebtMeasure(50);
343 measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, remediationEffortKey, newDebtMeasure);
344 measureRepository.addRawMeasure(111, remediationEffortKey, createNewDebtMeasure(150));
345 measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(250));
346 // 4 lines file, only first one is not ncloc
347 measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNclocDataMeasure(2, 3, 4));
348 // first 2 lines are before all snapshots, 2 last lines are after PERIOD 2's snapshot date
350 setNewLines(file, 3, 4);
352 underTest.visit(treeRootHolder.getRoot());
354 assertNewRating(ratingKey, LANGUAGE_1_FILE_REF, D);
355 assertNewRating(ratingKey, 111, D);
356 assertNewRating(ratingKey, ROOT_REF, D);
360 @MethodSource("metrics")
361 void compute_new_maintainability_rating_map_to_D(String remediationEffortKey, String debtRatioKey, String ratingKey) {
362 ReportComponent file = builder(FILE, LANGUAGE_1_FILE_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_1_KEY, 1)).build();
363 treeRootHolder.setRoot(
364 builder(PROJECT, ROOT_REF)
366 builder(DIRECTORY, 111)
371 Measure newDebtMeasure = createNewDebtMeasure(400);
372 measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, remediationEffortKey, newDebtMeasure);
373 measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNclocDataMeasure(2, 3, 4));
375 setNewLines(file, 3, 4);
377 underTest.visit(treeRootHolder.getRoot());
379 if (ratingKey.equals(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY)) {
380 assertNewRating(ratingKey, LANGUAGE_1_FILE_REF, D);
381 } else if (ratingKey.equals(NEW_MAINTAINABILITY_RATING_KEY)) {
382 assertNewRating(ratingKey, LANGUAGE_1_FILE_REF, E);
387 void compute_new_development_cost() {
388 ReportComponent file1 = builder(FILE, LANGUAGE_1_FILE_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_1_KEY, 4)).build();
389 ReportComponent file2 = builder(FILE, 22_222).setFileAttributes(new FileAttributes(false, LANGUAGE_1_KEY, 6)).build();
390 treeRootHolder.setRoot(
391 builder(PROJECT, ROOT_REF)
393 builder(DIRECTORY, 111)
394 .addChildren(file1, file2)
398 // 4 lines file, only first one is not ncloc
399 measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNclocDataMeasure(2, 3, 4));
400 // first 2 lines are before all snapshots, 2 last lines are after PERIOD 2's snapshot date
401 setNewLines(file1, 3, 4);
403 // 6 lines file, only last one is not ncloc
404 measureRepository.addRawMeasure(22_222, NCLOC_DATA_KEY, createNclocDataMeasure(1, 2, 3, 4, 5));
405 // first 2 lines are before all snapshots, 4 last lines are after PERIOD 2's snapshot date
406 setNewLines(file2, 3, 4, 5, 6);
408 underTest.visit(treeRootHolder.getRoot());
410 assertNewDevelopmentCostValues(ROOT_REF, 5 * DEV_COST);
411 assertNewDevelopmentCostValues(LANGUAGE_1_FILE_REF, 2 * DEV_COST);
412 assertNewDevelopmentCostValues(22_222, 3 * DEV_COST);
416 @MethodSource("metrics")
417 void compute_new_maintainability_rating_to_A_when_no_debt(String remediationEffortKey, String debtRatioKey, String ratingKey) {
418 when(newLinesRepository.newLinesAvailable()).thenReturn(true);
419 treeRootHolder.setRoot(
420 builder(PROJECT, ROOT_REF)
422 builder(DIRECTORY, 111)
424 builder(FILE, LANGUAGE_1_FILE_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_1_KEY, 1)).build())
428 underTest.visit(treeRootHolder.getRoot());
430 assertNewRating(ratingKey, LANGUAGE_1_FILE_REF, A);
431 assertNewRating(ratingKey, 111, A);
432 assertNewRating(ratingKey, ROOT_REF, A);
435 private void setupOneFileAloneInAProject(String remediationEffortKey, int newDebt, Flag isUnitTest, Flag withNclocLines, Flag withNewLines) {
436 checkArgument(isUnitTest == Flag.UT_FILE || isUnitTest == Flag.SRC_FILE);
437 checkArgument(withNclocLines == Flag.WITH_NCLOC || withNclocLines == Flag.NO_NCLOC || withNclocLines == Flag.MISSING_MEASURE_NCLOC);
438 checkArgument(withNewLines == Flag.WITH_NEW_LINES || withNewLines == Flag.NO_NEW_LINES);
440 Component file = builder(FILE, LANGUAGE_1_FILE_REF).setFileAttributes(new FileAttributes(isUnitTest == Flag.UT_FILE, LANGUAGE_1_KEY, 1)).build();
441 treeRootHolder.setRoot(
442 builder(PROJECT, ROOT_REF)
446 Measure newDebtMeasure = createNewDebtMeasure(newDebt);
447 measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, remediationEffortKey, newDebtMeasure);
448 if (withNclocLines == Flag.WITH_NCLOC) {
449 // 4 lines file, only first one is not ncloc
450 measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNclocDataMeasure(2, 3, 4));
451 } else if (withNclocLines == Flag.NO_NCLOC) {
452 // 4 lines file, none of which is ncloc
453 measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNoNclocDataMeasure(4));
455 if (withNewLines == Flag.WITH_NEW_LINES) {
456 // 2 last lines are new
457 setNewLines(file, 3, 4);
461 private void setNewLines(Component component, int... lineNumbers) {
462 HashSet<Integer> newLines = new HashSet<>();
463 for (int i : lineNumbers) {
466 when(newLinesRepository.newLinesAvailable()).thenReturn(true);
467 when(newLinesRepository.getNewLines(component)).thenReturn(Optional.of(newLines));
472 UT_FILE, SRC_FILE, NO_NEW_LINES, WITH_NEW_LINES, WITH_NCLOC, NO_NCLOC, MISSING_MEASURE_NCLOC
475 public static ReportComponent.Builder builder(Component.Type type, int ref) {
476 return ReportComponent.builder(type, ref).setKey(String.valueOf(ref));
479 private Measure createNewDebtMeasure(long value) {
480 return newMeasureBuilder().create(value);
483 private static Measure createNclocDataMeasure(Integer... nclocLines) {
484 Set<Integer> nclocLinesSet = ImmutableSet.copyOf(nclocLines);
485 int max = Ordering.<Integer>natural().max(nclocLinesSet);
486 ImmutableMap.Builder<Integer, Integer> builder = ImmutableMap.builder();
487 for (int i = 1; i <= max; i++) {
488 builder.put(i, nclocLinesSet.contains(i) ? 1 : 0);
490 return newMeasureBuilder().create(KeyValueFormat.format(builder.build(), KeyValueFormat.newIntegerConverter(), KeyValueFormat.newIntegerConverter()));
493 private static Measure createNoNclocDataMeasure(int lineCount) {
494 ImmutableMap.Builder<Integer, Integer> builder = ImmutableMap.builder();
495 for (int i = 1; i <= lineCount; i++) {
498 return newMeasureBuilder().create(KeyValueFormat.format(builder.build(), KeyValueFormat.newIntegerConverter(), KeyValueFormat.newIntegerConverter()));
501 private void assertNoNewDebtRatioMeasure(String debtRatioKey, int componentRef) {
502 assertThat(measureRepository.getAddedRawMeasure(componentRef, debtRatioKey))
506 private void assertNewDebtRatioValues(String debtRatioKey, int componentRef, double expectedValue) {
507 assertThat(measureRepository.getAddedRawMeasure(componentRef, debtRatioKey)).hasValue(expectedValue, VALUE_COMPARISON_OFFSET);
510 private void assertNewDevelopmentCostValues(int componentRef, float expectedValue) {
511 assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_DEVELOPMENT_COST_KEY)).hasValue(expectedValue, VALUE_COMPARISON_OFFSET);
514 private void assertNewRating(String ratingKey, int componentRef, Rating expectedValue) {
515 assertThat(measureRepository.getAddedRawMeasure(componentRef, ratingKey)).hasValue(expectedValue.getIndex());
518 private void assertNoNewMaintainability(String ratingKey, int componentRef) {
519 assertThat(measureRepository.getAddedRawMeasure(componentRef, ratingKey))