]> source.dussan.org Git - sonarqube.git/blob
27f402162b65b94f0ea341ebfb060b534a5e486f
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2016 SonarSource SA
4  * mailto:contact AT sonarsource DOT com
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 package org.sonar.server.computation.qualitymodel;
21
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.Set;
27 import org.assertj.core.data.Offset;
28 import org.junit.Rule;
29 import org.junit.Test;
30 import org.sonar.api.utils.KeyValueFormat;
31 import org.sonar.server.computation.batch.TreeRootHolderRule;
32 import org.sonar.server.computation.component.Component;
33 import org.sonar.server.computation.component.ComponentVisitor;
34 import org.sonar.server.computation.component.FileAttributes;
35 import org.sonar.server.computation.component.ReportComponent;
36 import org.sonar.server.computation.component.VisitorsCrawler;
37 import org.sonar.server.computation.measure.Measure;
38 import org.sonar.server.computation.measure.MeasureRepositoryRule;
39 import org.sonar.server.computation.measure.MeasureVariations;
40 import org.sonar.server.computation.metric.MetricRepositoryRule;
41 import org.sonar.server.computation.period.Period;
42 import org.sonar.server.computation.period.PeriodsHolderRule;
43 import org.sonar.server.computation.scm.Changeset;
44 import org.sonar.server.computation.scm.ScmInfoRepositoryRule;
45
46 import static com.google.common.base.Preconditions.checkArgument;
47 import static org.mockito.Mockito.mock;
48 import static org.mockito.Mockito.when;
49 import static org.sonar.api.measures.CoreMetrics.NCLOC_DATA;
50 import static org.sonar.api.measures.CoreMetrics.NCLOC_DATA_KEY;
51 import static org.sonar.api.measures.CoreMetrics.NEW_SQALE_DEBT_RATIO;
52 import static org.sonar.api.measures.CoreMetrics.NEW_SQALE_DEBT_RATIO_KEY;
53 import static org.sonar.api.measures.CoreMetrics.NEW_TECHNICAL_DEBT;
54 import static org.sonar.api.measures.CoreMetrics.NEW_TECHNICAL_DEBT_KEY;
55 import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
56 import static org.sonar.server.computation.component.Component.Type.FILE;
57 import static org.sonar.server.computation.component.Component.Type.MODULE;
58 import static org.sonar.server.computation.component.Component.Type.PROJECT;
59 import static org.sonar.server.computation.measure.Measure.newMeasureBuilder;
60 import static org.sonar.server.computation.measure.MeasureAssert.assertThat;
61
62 public class NewQualityModelMeasuresVisitorTest {
63   private static final String LANGUAGE_1_KEY = "language 1 key";
64   private static final long LANGUAGE_1_DEV_COST = 30l;
65   private static final long PERIOD_2_SNAPSHOT_DATE = 12323l;
66   private static final long PERIOD_5_SNAPSHOT_DATE = 99999999l;
67   private static final String SOME_ANALYSIS_UUID = "9993l";
68   private static final String SOME_PERIOD_MODE = "some mode";
69   private static final int ROOT_REF = 1;
70   private static final int LANGUAGE_1_FILE_REF = 11111;
71   private static final Offset<Double> VARIATION_COMPARISON_OFFSET = Offset.offset(0.01);
72
73   @Rule
74   public ScmInfoRepositoryRule scmInfoRepository = new ScmInfoRepositoryRule();
75   @Rule
76   public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
77   @Rule
78   public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
79     .add(NEW_TECHNICAL_DEBT)
80     .add(NCLOC_DATA)
81     .add(NEW_SQALE_DEBT_RATIO);
82   @Rule
83   public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
84   @Rule
85   public PeriodsHolderRule periodsHolder = new PeriodsHolderRule();
86
87   private RatingSettings ratingSettings = mock(RatingSettings.class);
88
89   private VisitorsCrawler underTest = new VisitorsCrawler(Arrays.<ComponentVisitor>asList(new NewQualityModelMeasuresVisitor(metricRepository, measureRepository, scmInfoRepository,
90     periodsHolder, ratingSettings)));
91
92   @Test
93   public void project_has_new_debt_ratio_variation_for_each_defined_period() {
94     setTwoPeriods();
95     treeRootHolder.setRoot(builder(PROJECT, ROOT_REF).build());
96
97     underTest.visit(treeRootHolder.getRoot());
98
99     assertNewDebtRatioValues(ROOT_REF, 0, 0);
100   }
101
102   @Test
103   public void project_has_no_new_debt_ratio_variation_if_there_is_no_period() {
104     periodsHolder.setPeriods();
105     treeRootHolder.setRoot(builder(PROJECT, ROOT_REF).build());
106
107     underTest.visit(treeRootHolder.getRoot());
108
109     assertNoNewDebtRatioMeasure(ROOT_REF);
110   }
111
112   @Test
113   public void file_has_no_new_debt_ratio_variation_if_there_is_no_period() {
114     periodsHolder.setPeriods();
115     when(ratingSettings.getDevCost(LANGUAGE_1_KEY)).thenReturn(LANGUAGE_1_DEV_COST);
116     setupOneFileAloneInAProject(50, 12, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_CHANGESET);
117     measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(50, 12));
118
119     underTest.visit(treeRootHolder.getRoot());
120
121     assertNoNewDebtRatioMeasure(LANGUAGE_1_FILE_REF);
122     assertNoNewDebtRatioMeasure(ROOT_REF);
123   }
124
125   @Test
126   public void file_has_0_new_debt_ratio_if_all_scm_dates_are_before_snapshot_dates() {
127     setTwoPeriods();
128     treeRootHolder.setRoot(
129       builder(PROJECT, ROOT_REF)
130         .addChildren(
131           builder(FILE, LANGUAGE_1_FILE_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_1_KEY)).build()
132         )
133         .build()
134     );
135     measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(50, 12));
136     measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNclocDataMeasure(2, 3, 4));
137     scmInfoRepository.setScmInfo(LANGUAGE_1_FILE_REF, createChangesets(PERIOD_2_SNAPSHOT_DATE - 100, 4));
138
139     underTest.visit(treeRootHolder.getRoot());
140
141     assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 0, 0);
142     assertNewDebtRatioValues(ROOT_REF, 0, 0);
143   }
144
145   @Test
146   public void file_has_new_debt_ratio_if_some_scm_dates_are_after_snapshot_dates() {
147     setTwoPeriods();
148     when(ratingSettings.getDevCost(LANGUAGE_1_KEY)).thenReturn(LANGUAGE_1_DEV_COST);
149     setupOneFileAloneInAProject(50, 12, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_CHANGESET);
150     measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(50, 12));
151
152     underTest.visit(treeRootHolder.getRoot());
153
154     assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 83.33, 0);
155     assertNewDebtRatioValues(ROOT_REF, 83.33, 0);
156   }
157
158   @Test
159   public void new_debt_ratio_changes_with_language_cost() {
160     setTwoPeriods();
161     when(ratingSettings.getDevCost(LANGUAGE_1_KEY)).thenReturn(LANGUAGE_1_DEV_COST * 10);
162     setupOneFileAloneInAProject(50, 12, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_CHANGESET);
163     measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(50, 12));
164
165     underTest.visit(treeRootHolder.getRoot());
166
167     assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 8.33, 0);
168     assertNewDebtRatioValues(ROOT_REF, 8.33, 0);
169   }
170
171   @Test
172   public void new_debt_ratio_changes_with_new_technical_debt() {
173     setTwoPeriods();
174     when(ratingSettings.getDevCost(LANGUAGE_1_KEY)).thenReturn(LANGUAGE_1_DEV_COST);
175     setupOneFileAloneInAProject(500, 120, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_CHANGESET);
176     measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(500, 120));
177
178     underTest.visit(treeRootHolder.getRoot());
179
180     assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 833.33, 0);
181     assertNewDebtRatioValues(ROOT_REF, 833.33, 0);
182   }
183
184   @Test
185   public void new_debt_ratio_on_non_file_level_is_based_on_new_technical_debt_of_that_level() {
186     setTwoPeriods();
187     when(ratingSettings.getDevCost(LANGUAGE_1_KEY)).thenReturn(LANGUAGE_1_DEV_COST);
188     setupOneFileAloneInAProject(500, 120, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_CHANGESET);
189     measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(1200, 820));
190
191     underTest.visit(treeRootHolder.getRoot());
192
193     assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 833.33, 0);
194     assertNewDebtRatioValues(ROOT_REF, 833.33, 0);
195   }
196
197   @Test
198   public void no_new_debt_ratio_when_file_is_unit_test() {
199     setTwoPeriods();
200     when(ratingSettings.getDevCost(LANGUAGE_1_KEY)).thenReturn(LANGUAGE_1_DEV_COST);
201     setupOneFileAloneInAProject(50, 12, Flag.UT_FILE, Flag.WITH_NCLOC, Flag.WITH_CHANGESET);
202     measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(50, 12));
203
204     underTest.visit(treeRootHolder.getRoot());
205
206     assertNoNewDebtRatioMeasure(LANGUAGE_1_FILE_REF);
207     assertNewDebtRatioValues(ROOT_REF, 0, 0);
208   }
209
210   @Test
211   public void new_debt_ratio_is_0_on_non_file_level_when_all_files_are_unit_test() {
212     setTwoPeriods();
213     when(ratingSettings.getDevCost(LANGUAGE_1_KEY)).thenReturn(LANGUAGE_1_DEV_COST);
214     setupOneFileAloneInAProject(50, 12, Flag.UT_FILE, Flag.WITH_NCLOC, Flag.WITH_CHANGESET);
215     measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(200, 162));
216
217     underTest.visit(treeRootHolder.getRoot());
218
219     assertNoNewDebtRatioMeasure(LANGUAGE_1_FILE_REF);
220     assertNewDebtRatioValues(ROOT_REF, 0, 0);
221   }
222
223   @Test
224   public void new_debt_ratio_is_0_when_file_has_no_changesets() {
225     setTwoPeriods();
226     when(ratingSettings.getDevCost(LANGUAGE_1_KEY)).thenReturn(LANGUAGE_1_DEV_COST);
227     setupOneFileAloneInAProject(50, 12, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.NO_CHANGESET);
228     measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(50, 12));
229
230     underTest.visit(treeRootHolder.getRoot());
231
232     assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 0, 0);
233     assertNewDebtRatioValues(ROOT_REF, 0, 0);
234   }
235
236   @Test
237   public void new_debt_ratio_is_0_on_non_file_level_when_no_file_has_changesets() {
238     setTwoPeriods();
239     when(ratingSettings.getDevCost(LANGUAGE_1_KEY)).thenReturn(LANGUAGE_1_DEV_COST);
240     setupOneFileAloneInAProject(50, 12, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.NO_CHANGESET);
241     measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(200, 162));
242
243     underTest.visit(treeRootHolder.getRoot());
244
245     assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 0, 0);
246     assertNewDebtRatioValues(ROOT_REF, 0, 0);
247   }
248
249   @Test
250   public void new_debt_ratio_is_0_when_there_is_no_ncloc_in_file() {
251     setTwoPeriods();
252     when(ratingSettings.getDevCost(LANGUAGE_1_KEY)).thenReturn(LANGUAGE_1_DEV_COST);
253     setupOneFileAloneInAProject(50, 12, Flag.SRC_FILE, Flag.NO_NCLOC, Flag.WITH_CHANGESET);
254     measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(50, 12));
255
256     underTest.visit(treeRootHolder.getRoot());
257
258     assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 0, 0);
259     assertNewDebtRatioValues(ROOT_REF, 0, 0);
260   }
261
262   @Test
263   public void new_debt_ratio_is_0_on_non_file_level_when_one_file_has_zero_new_debt_because_of_no_changeset() {
264     setTwoPeriods();
265     when(ratingSettings.getDevCost(LANGUAGE_1_KEY)).thenReturn(LANGUAGE_1_DEV_COST);
266     setupOneFileAloneInAProject(50, 12, Flag.SRC_FILE, Flag.NO_NCLOC, Flag.WITH_CHANGESET);
267     measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(200, 162));
268
269     underTest.visit(treeRootHolder.getRoot());
270
271     assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 0, 0);
272     assertNewDebtRatioValues(ROOT_REF, 0, 0);
273   }
274
275   @Test
276   public void new_debt_ratio_is_0_when_ncloc_measure_is_missing() {
277     setTwoPeriods();
278     when(ratingSettings.getDevCost(LANGUAGE_1_KEY)).thenReturn(LANGUAGE_1_DEV_COST);
279     setupOneFileAloneInAProject(50, 12, Flag.SRC_FILE, Flag.MISSING_MEASURE_NCLOC, Flag.WITH_CHANGESET);
280     measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(50, 12));
281
282     underTest.visit(treeRootHolder.getRoot());
283
284     assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 0, 0);
285     assertNewDebtRatioValues(ROOT_REF, 0, 0);
286   }
287
288   @Test
289   public void leaf_components_always_have_a_measure_when_at_least_one_period_exist_and_ratio_is_computed_from_current_level_new_debt() {
290     setTwoPeriods();
291     when(ratingSettings.getDevCost(LANGUAGE_1_KEY)).thenReturn(LANGUAGE_1_DEV_COST);
292     treeRootHolder.setRoot(
293       builder(PROJECT, ROOT_REF)
294         .addChildren(
295           builder(MODULE, 11)
296             .addChildren(
297               builder(DIRECTORY, 111)
298                 .addChildren(
299                   builder(FILE, LANGUAGE_1_FILE_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_1_KEY)).build()
300                 ).build()
301             ).build()
302         ).build()
303     );
304
305     Measure newDebtMeasure = createNewDebtMeasure(50, 12);
306     measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NEW_TECHNICAL_DEBT_KEY, newDebtMeasure);
307     measureRepository.addRawMeasure(111, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(150, 112));
308     measureRepository.addRawMeasure(11, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(200, 112));
309     measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(250, 212));
310     // 4 lines file, only first one is not ncloc
311     measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNclocDataMeasure(2, 3, 4));
312     // first 2 lines are before all snapshots, 2 last lines are after PERIOD 2's snapshot date
313     scmInfoRepository.setScmInfo(LANGUAGE_1_FILE_REF, createChangesets(PERIOD_2_SNAPSHOT_DATE - 100, 2, PERIOD_2_SNAPSHOT_DATE + 100, 2));
314
315     underTest.visit(treeRootHolder.getRoot());
316
317     assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 83.33, 0);
318     assertNewDebtRatioValues(111, 83.33, 0);
319     assertNewDebtRatioValues(11, 83.33, 0);
320     assertNewDebtRatioValues(ROOT_REF, 83.33, 0);
321   }
322
323   @Test
324   public void new_debt_ratio_is_computed_for_five_periods() throws Exception {
325     long period1 = 10000L;
326     long period2 = 20000L;
327     long period3 = 30000L;
328     long period4 = 40000L;
329     long period5 = 50000L;
330
331     periodsHolder.setPeriods(
332       new Period(1, SOME_PERIOD_MODE, null, period1, SOME_ANALYSIS_UUID),
333       new Period(2, SOME_PERIOD_MODE, null, period2, SOME_ANALYSIS_UUID),
334       new Period(3, SOME_PERIOD_MODE, null, period3, SOME_ANALYSIS_UUID),
335       new Period(4, SOME_PERIOD_MODE, null, period4, SOME_ANALYSIS_UUID),
336       new Period(5, SOME_PERIOD_MODE, null, period5, SOME_ANALYSIS_UUID));
337
338     when(ratingSettings.getDevCost(LANGUAGE_1_KEY)).thenReturn(LANGUAGE_1_DEV_COST);
339
340     treeRootHolder.setRoot(
341       builder(PROJECT, ROOT_REF)
342         .addChildren(builder(FILE, LANGUAGE_1_FILE_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_1_KEY)).build())
343         .build()
344     );
345
346     Measure newDebtMeasure = newMeasureBuilder().setVariations(new MeasureVariations(500d, 500d, 500d, 120d, 120d)).createNoValue();
347     measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NEW_TECHNICAL_DEBT_KEY, newDebtMeasure);
348     // 4 lines file, only first one is not ncloc
349     measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNclocDataMeasure(2, 3, 4));
350     // first 2 lines are before all snapshots, 2 last lines are after PERIOD 2's snapshot date
351     scmInfoRepository.setScmInfo(LANGUAGE_1_FILE_REF, createChangesets(period2 - 100, 2, period2 + 100, 2));
352
353     measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY,
354       newMeasureBuilder().setVariations(new MeasureVariations(1200d, 1200d, 1200d, 820d, 820d)).createNoValue());
355
356     underTest.visit(treeRootHolder.getRoot());
357
358     assertThat(measureRepository.getAddedRawMeasure(LANGUAGE_1_FILE_REF, NEW_SQALE_DEBT_RATIO_KEY))
359       .hasVariation1(833.333, VARIATION_COMPARISON_OFFSET)
360       .hasVariation2(833.333, VARIATION_COMPARISON_OFFSET)
361       .hasVariation3(0d, VARIATION_COMPARISON_OFFSET)
362       .hasVariation4(0d, VARIATION_COMPARISON_OFFSET)
363       .hasVariation5(0d, VARIATION_COMPARISON_OFFSET);
364   }
365
366   private void setupOneFileAloneInAProject(int newDebtPeriod2, int newDebtPeriod4, Flag isUnitTest, Flag withNclocLines, Flag withChangeSets) {
367     checkArgument(isUnitTest == Flag.UT_FILE || isUnitTest == Flag.SRC_FILE);
368     checkArgument(withNclocLines == Flag.WITH_NCLOC || withNclocLines == Flag.NO_NCLOC || withNclocLines == Flag.MISSING_MEASURE_NCLOC);
369     checkArgument(withChangeSets == Flag.WITH_CHANGESET || withChangeSets == Flag.NO_CHANGESET);
370
371     treeRootHolder.setRoot(
372       builder(PROJECT, ROOT_REF)
373         .addChildren(
374           builder(FILE, LANGUAGE_1_FILE_REF).setFileAttributes(new FileAttributes(isUnitTest == Flag.UT_FILE, LANGUAGE_1_KEY)).build()
375         )
376         .build()
377     );
378
379     Measure newDebtMeasure = createNewDebtMeasure(newDebtPeriod2, newDebtPeriod4);
380     measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NEW_TECHNICAL_DEBT_KEY, newDebtMeasure);
381     if (withNclocLines == Flag.WITH_NCLOC) {
382       // 4 lines file, only first one is not ncloc
383       measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNclocDataMeasure(2, 3, 4));
384     } else if (withNclocLines == Flag.NO_NCLOC) {
385       // 4 lines file, none of which is ncloc
386       measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNoNclocDataMeasure(4));
387     }
388     if (withChangeSets == Flag.WITH_CHANGESET) {
389       // first 2 lines are before all snapshots, 2 last lines are after PERIOD 2's snapshot date
390       scmInfoRepository.setScmInfo(LANGUAGE_1_FILE_REF, createChangesets(PERIOD_2_SNAPSHOT_DATE - 100, 2, PERIOD_2_SNAPSHOT_DATE + 100, 2));
391     }
392   }
393
394   private enum Flag {
395     UT_FILE, SRC_FILE, NO_CHANGESET, WITH_CHANGESET, WITH_NCLOC, NO_NCLOC, MISSING_MEASURE_NCLOC
396   }
397
398   public static ReportComponent.Builder builder(Component.Type type, int ref) {
399     return ReportComponent.builder(type, ref).setKey(String.valueOf(ref));
400   }
401
402   private Measure createNewDebtMeasure(double period2Value, double period4Value) {
403     return newMeasureBuilder().setVariations(new MeasureVariations(null, period2Value, null, period4Value, null)).createNoValue();
404   }
405
406   private static Measure createNclocDataMeasure(Integer... nclocLines) {
407     Set<Integer> nclocLinesSet = ImmutableSet.copyOf(nclocLines);
408     int max = Ordering.<Integer>natural().max(nclocLinesSet);
409     ImmutableMap.Builder<Integer, Integer> builder = ImmutableMap.builder();
410     for (int i = 1; i <= max; i++) {
411       builder.put(i, nclocLinesSet.contains(i) ? 1 : 0);
412     }
413     return newMeasureBuilder().create(KeyValueFormat.format(builder.build(), KeyValueFormat.newIntegerConverter(), KeyValueFormat.newIntegerConverter()));
414   }
415
416   private static Measure createNoNclocDataMeasure(int lineCount) {
417     ImmutableMap.Builder<Integer, Integer> builder = ImmutableMap.builder();
418     for (int i = 1; i <= lineCount; i++) {
419       builder.put(i, 0);
420     }
421     return newMeasureBuilder().create(KeyValueFormat.format(builder.build(), KeyValueFormat.newIntegerConverter(), KeyValueFormat.newIntegerConverter()));
422   }
423
424   /**
425    * Creates changesets of {@code lines} lines which all have the same date {@code scmDate}.
426    */
427   private static Changeset[] createChangesets(long scmDate, int lines) {
428     Changeset changetset = Changeset.newChangesetBuilder().setDate(scmDate).setRevision("rev-1").build();
429     Changeset[] changesets = new Changeset[lines];
430     for (int i = 0; i < lines; i++) {
431       changesets[i] = changetset;
432     }
433     return changesets;
434   }
435
436   /**
437    * Creates a changeset of {@code lineCount} lines which have the date {@code scmDate} and {@code otherLineCount} lines which
438    * have the date {@code otherScmDate}.
439    */
440   private static Changeset[] createChangesets(long scmDate, int lineCount, long otherScmDate, int otherLineCount) {
441     Changeset[] changesets = new Changeset[lineCount + otherLineCount];
442     Changeset changetset1 = Changeset.newChangesetBuilder().setDate(scmDate).setRevision("rev-1").build();
443     for (int i = 0; i < lineCount; i++) {
444       changesets[i] = changetset1;
445     }
446     Changeset changetset2 = Changeset.newChangesetBuilder().setDate(otherScmDate).setRevision("rev-2").build();
447     for (int i = lineCount; i < lineCount + otherLineCount; i++) {
448       changesets[i] = changetset2;
449     }
450     return changesets;
451   }
452
453   private void assertNoNewDebtRatioMeasure(int componentRef) {
454     assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SQALE_DEBT_RATIO_KEY))
455       .isAbsent();
456   }
457
458   private void assertNewDebtRatioValues(int componentRef, double expectedPeriod2Value, double expectedPeriod4Value) {
459     assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SQALE_DEBT_RATIO_KEY))
460       .hasVariation2(expectedPeriod2Value, VARIATION_COMPARISON_OFFSET)
461       .hasVariation4(expectedPeriod4Value, VARIATION_COMPARISON_OFFSET);
462   }
463
464   private void setTwoPeriods() {
465     periodsHolder.setPeriods(
466       new Period(2, SOME_PERIOD_MODE, null, PERIOD_2_SNAPSHOT_DATE, SOME_ANALYSIS_UUID),
467       new Period(4, SOME_PERIOD_MODE, null, PERIOD_5_SNAPSHOT_DATE, SOME_ANALYSIS_UUID));
468   }
469 }