import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
+import java.util.HashSet;
+import java.util.Set;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.sonar.api.measures.CoreMetrics;
-import org.sonar.server.computation.component.CrawlerDepthLimit;
+import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.PathAwareCrawler;
import org.sonar.server.computation.component.TreeRootHolder;
+import org.sonar.server.computation.duplication.Duplication;
+import org.sonar.server.computation.duplication.DuplicationRepository;
+import org.sonar.server.computation.duplication.InnerDuplicate;
+import org.sonar.server.computation.duplication.TextBlock;
import org.sonar.server.computation.formula.Counter;
import org.sonar.server.computation.formula.CounterInitializationContext;
import org.sonar.server.computation.formula.CreateMeasureContext;
import org.sonar.server.computation.formula.Formula;
import org.sonar.server.computation.formula.FormulaExecutorComponentVisitor;
-import org.sonar.server.computation.formula.counter.IntSumCounter;
import org.sonar.server.computation.measure.Measure;
import org.sonar.server.computation.measure.MeasureRepository;
import org.sonar.server.computation.metric.Metric;
import org.sonar.server.computation.metric.MetricRepository;
+import static com.google.common.collect.FluentIterable.from;
import static java.util.Objects.requireNonNull;
import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES_KEY;
import static org.sonar.api.measures.CoreMetrics.DUPLICATED_BLOCKS_KEY;
private final MetricRepository metricRepository;
private final MeasureRepository measureRepository;
- public DuplicationMeasuresStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository) {
+ public DuplicationMeasuresStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository,
+ @Nullable DuplicationRepository duplicationRepository) {
this.treeRootHolder = treeRootHolder;
this.metricRepository = metricRepository;
this.measureRepository = measureRepository;
- this.formulas = ImmutableList.<Formula>of(
- new SumDuplicationFormula(DUPLICATED_BLOCKS_KEY),
- new SumDuplicationFormula(DUPLICATED_FILES_KEY),
- new DuplicationFormula());
+ this.formulas = ImmutableList.<Formula>of(new DuplicationFormula(metricRepository, measureRepository, duplicationRepository));
+ }
+
+ /**
+ * Constructor used by Pico in Views where no DuplicationRepository is available.
+ */
+ public DuplicationMeasuresStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository) {
+ this(treeRootHolder, metricRepository, measureRepository, null);
+ }
+
+ @Override
+ public String getDescription() {
+ return "Compute duplication measures";
}
@Override
public void execute() {
new PathAwareCrawler<>(
FormulaExecutorComponentVisitor.newBuilder(metricRepository, measureRepository).buildFor(formulas))
- .visit(treeRootHolder.getRoot());
+ .visit(treeRootHolder.getRoot());
}
- private class DuplicationFormula implements Formula<SumDuplicationCounter> {
+ private static class DuplicationCounter implements Counter<DuplicationCounter> {
+ @CheckForNull
+ private final DuplicationRepository duplicationRepository;
+ private int fileCount = 0;
+ private int blockCount = 0;
+ private int lineCount = 0;
+
+ private DuplicationCounter(@Nullable DuplicationRepository duplicationRepository) {
+ this.duplicationRepository = duplicationRepository;
+ }
+
+ @Override
+ public void aggregate(DuplicationCounter counter) {
+ this.fileCount += counter.fileCount;
+ this.blockCount += counter.blockCount;
+ this.lineCount += counter.lineCount;
+ }
+
+ @Override
+ public void initialize(CounterInitializationContext context) {
+ Component leaf = context.getLeaf();
+ if (leaf.getType() == Component.Type.FILE) {
+ initializeForFile(leaf);
+ } else if (leaf.getType() == Component.Type.PROJECT_VIEW) {
+ initializeForProjectView(context);
+ }
+ }
+
+ private void initializeForFile(Component file) {
+ Set<Duplication> duplications = requireNonNull(this.duplicationRepository, "DuplicationRepository missing")
+ .getDuplications(file);
+ if (duplications.isEmpty()) {
+ return;
+ }
+
+ // use a set to count lines only once
+ Set<Integer> duplicatedLineNumbers = new HashSet<>();
+ long blocks = 0;
+ for (Duplication duplication : duplications) {
+ blocks++;
+ addLines(duplication.getOriginal(), duplicatedLineNumbers);
+ for (InnerDuplicate innerDuplicate : from(duplication.getDuplicates()).filter(InnerDuplicate.class)) {
+ blocks++;
+ addLines(innerDuplicate.getTextBlock(), duplicatedLineNumbers);
+ }
+ }
+
+ this.fileCount += 1;
+ this.blockCount += blocks;
+ this.lineCount += duplicatedLineNumbers.size();
+ }
+
+ private static void addLines(TextBlock textBlock, Set<Integer> duplicatedLineNumbers) {
+ for (int i = textBlock.getStart(); i <= textBlock.getEnd(); i++) {
+ duplicatedLineNumbers.add(i);
+ }
+ }
+
+ private void initializeForProjectView(CounterInitializationContext context) {
+ fileCount += getMeasure(context, DUPLICATED_FILES_KEY);
+ blockCount += getMeasure(context, DUPLICATED_BLOCKS_KEY);
+ lineCount += getMeasure(context, DUPLICATED_LINES_KEY);
+ }
+
+ private static int getMeasure(CounterInitializationContext context, String metricKey) {
+ Optional<Measure> files = context.getMeasure(metricKey);
+ if (files.isPresent()) {
+ return files.get().getIntValue();
+ }
+ return 0;
+ }
+ }
+ private static final class DuplicationFormula implements Formula<DuplicationCounter> {
+ private final MeasureRepository measureRepository;
+ @CheckForNull
+ private final DuplicationRepository duplicationRepository;
private final Metric nclocMetric;
private final Metric linesMetric;
private final Metric commentLinesMetric;
- public DuplicationFormula() {
+ private DuplicationFormula(MetricRepository metricRepository, MeasureRepository measureRepository, @Nullable DuplicationRepository duplicationRepository) {
+ this.measureRepository = measureRepository;
+ this.duplicationRepository = duplicationRepository;
this.nclocMetric = metricRepository.getByKey(NCLOC_KEY);
this.linesMetric = metricRepository.getByKey(LINES_KEY);
this.commentLinesMetric = metricRepository.getByKey(COMMENT_LINES_KEY);
}
@Override
- public SumDuplicationCounter createNewCounter() {
- return new SumDuplicationCounter(DUPLICATED_LINES_KEY);
+ public DuplicationCounter createNewCounter() {
+ return new DuplicationCounter(duplicationRepository);
}
@Override
- public Optional<Measure> createMeasure(SumDuplicationCounter counter, CreateMeasureContext context) {
- return createDuplicatedLinesMeasure(counter, context)
- .or(createDuplicatedLinesDensityMeasure(counter, context));
- }
-
- private Optional<Measure> createDuplicatedLinesMeasure(SumDuplicationCounter counter, CreateMeasureContext context) {
- int duplicatedLines = counter.value;
- if (context.getMetric().getKey().equals(DUPLICATED_LINES_KEY)
- && CrawlerDepthLimit.LEAVES.isDeeperThan(context.getComponent().getType())) {
- return Optional.of(Measure.newMeasureBuilder().create(duplicatedLines));
+ public Optional<Measure> createMeasure(DuplicationCounter counter, CreateMeasureContext context) {
+ switch (context.getMetric().getKey()) {
+ case DUPLICATED_FILES_KEY:
+ return Optional.of(Measure.newMeasureBuilder().create(counter.fileCount));
+ case DUPLICATED_LINES_KEY:
+ return Optional.of(Measure.newMeasureBuilder().create(counter.lineCount));
+ case DUPLICATED_LINES_DENSITY_KEY:
+ return createDuplicatedLinesDensityMeasure(counter, context);
+ case DUPLICATED_BLOCKS_KEY:
+ return Optional.of(Measure.newMeasureBuilder().create(counter.blockCount));
+ default:
+ throw new IllegalArgumentException("Unsupported metric " + context.getMetric());
}
- return Optional.absent();
}
- private Optional<Measure> createDuplicatedLinesDensityMeasure(SumDuplicationCounter counter, CreateMeasureContext context) {
- int duplicatedLines = counter.value;
- if (context.getMetric().getKey().equals(DUPLICATED_LINES_DENSITY_KEY)) {
- Optional<Integer> nbLines = getNbLinesFromLocOrNcloc(context);
- if (nbLines.isPresent() && nbLines.get() > 0) {
- double density = Math.min(100d, 100d * duplicatedLines / nbLines.get());
- return Optional.of(Measure.newMeasureBuilder().create(density));
- }
+ private Optional<Measure> createDuplicatedLinesDensityMeasure(DuplicationCounter counter, CreateMeasureContext context) {
+ int duplicatedLines = counter.lineCount;
+ Optional<Integer> nbLines = getNbLinesFromLocOrNcloc(context);
+ if (nbLines.isPresent() && nbLines.get() > 0) {
+ double density = Math.min(100d, 100d * duplicatedLines / nbLines.get());
+ return Optional.of(Measure.newMeasureBuilder().create(density));
}
return Optional.absent();
}
@Override
public String[] getOutputMetricKeys() {
- return new String[] {DUPLICATED_LINES_KEY, DUPLICATED_LINES_DENSITY_KEY};
- }
- }
-
- private class SumDuplicationFormula implements Formula<SumDuplicationCounter> {
-
- private final String metricKey;
-
- public SumDuplicationFormula(String metricKey) {
- this.metricKey = requireNonNull(metricKey, "Metric key cannot be null");
- }
-
- @Override
- public SumDuplicationCounter createNewCounter() {
- return new SumDuplicationCounter(metricKey);
- }
-
- @Override
- public Optional<Measure> createMeasure(SumDuplicationCounter counter, CreateMeasureContext context) {
- int value = counter.value;
- if (CrawlerDepthLimit.LEAVES.isDeeperThan(context.getComponent().getType())) {
- return Optional.of(Measure.newMeasureBuilder().create(value));
- }
- return Optional.absent();
- }
-
- @Override
- public String[] getOutputMetricKeys() {
- return new String[] {metricKey};
+ return new String[] {DUPLICATED_FILES_KEY, DUPLICATED_LINES_KEY, DUPLICATED_LINES_DENSITY_KEY, DUPLICATED_BLOCKS_KEY};
}
}
-
- /**
- * This counter is almost the same as {@link IntSumCounter}, expect that it will aggregate a value of 0 when there's no measure on file level
- */
- private class SumDuplicationCounter implements Counter<SumDuplicationCounter> {
-
- private final String metricKey;
-
- private int value = 0;
-
- public SumDuplicationCounter(String metricKey) {
- this.metricKey = metricKey;
- }
-
- @Override
- public void aggregate(SumDuplicationCounter counter) {
- value += counter.value;
- }
-
- @Override
- public void initialize(CounterInitializationContext context) {
- Optional<Measure> measureOptional = context.getMeasure(metricKey);
- if (measureOptional.isPresent()) {
- value += measureOptional.get().getIntValue();
- }
- }
- }
-
- @Override
- public String getDescription() {
- return "Compute duplication measures";
- }
}
import org.junit.Rule;
import org.junit.Test;
import org.sonar.server.computation.batch.TreeRootHolderRule;
+import org.sonar.server.computation.duplication.DuplicationRepositoryRule;
+import org.sonar.server.computation.duplication.TextBlock;
import org.sonar.server.computation.measure.MeasureRepositoryRule;
import org.sonar.server.computation.metric.MetricRepositoryRule;
+import static com.google.common.base.Preconditions.checkArgument;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.guava.api.Assertions.assertThat;
import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES;
private static final int ROOT_REF = 1;
private static final int MODULE_REF = 12;
- private static final int SUB_MODULE_REF = 123;
+ private static final int SUB_MODULE_1_REF = 123;
+ private static final int SUB_MODULE_2_REF = 126;
private static final int DIRECTORY_REF = 1234;
private static final int FILE_1_REF = 12341;
private static final int FILE_2_REF = 12342;
+ private static final int FILE_3_REF = 1261;
+ private static final int FILE_4_REF = 1262;
+ private static final String SOME_FILE_KEY = "some file key";
@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule()
.addChildren(
builder(MODULE, MODULE_REF)
.addChildren(
- builder(MODULE, SUB_MODULE_REF)
+ builder(MODULE, SUB_MODULE_1_REF)
.addChildren(
builder(DIRECTORY, DIRECTORY_REF)
.addChildren(
builder(FILE, FILE_1_REF).build(),
builder(FILE, FILE_2_REF).build())
.build())
+ .build(),
+ builder(MODULE, SUB_MODULE_2_REF)
+ .addChildren(
+ builder(FILE, FILE_3_REF).build(),
+ builder(FILE, FILE_4_REF).build()
+ )
.build())
.build())
.build());
.add(DUPLICATED_LINES_DENSITY);
@Rule
public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+ @Rule
+ public DuplicationRepositoryRule duplicationRepository = DuplicationRepositoryRule.create(treeRootHolder);
+
+ ComputationStep underTest = new DuplicationMeasuresStep(treeRootHolder, metricRepository, measureRepository, duplicationRepository);
+
+ @Test
+ public void compute_duplicated_blocks_one_for_original_one_for_each_InnerDuplicate() {
+ TextBlock original = new TextBlock(1, 1);
+ duplicationRepository.addDuplication(FILE_1_REF, original, new TextBlock(2, 2));
+ duplicationRepository.addDuplication(FILE_1_REF, original, new TextBlock(3, 3));
+ duplicationRepository.addDuplication(FILE_1_REF, original, new TextBlock(2, 3));
+
+ underTest.execute();
+
+ assertRawMeasureValue(FILE_1_REF, DUPLICATED_BLOCKS_KEY, 4);
+ }
+
+ @Test
+ public void compute_duplicated_blocks_does_not_count_blocks_only_once_it_assumes_consistency_from_duplication_data() {
+ duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 1), new TextBlock(3, 3));
+ duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(2, 2), new TextBlock(3, 3));
- ComputationStep underTest = new DuplicationMeasuresStep(treeRootHolder, metricRepository, measureRepository);
+ underTest.execute();
+
+ assertRawMeasureValue(FILE_1_REF, DUPLICATED_BLOCKS_KEY, 4);
+ }
@Test
- public void aggregate_duplicated_blocks() {
- addRawMeasure(FILE_1_REF, DUPLICATED_BLOCKS_KEY, 10);
- addRawMeasure(FILE_2_REF, DUPLICATED_BLOCKS_KEY, 40);
+ public void compute_duplicated_blocks_one_for_original_and_ignores_InProjectDuplicate() {
+ duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 1), FILE_2_REF, new TextBlock(2, 2));
underTest.execute();
- assertNoRawMeasure(FILE_1_REF, DUPLICATED_BLOCKS_KEY);
- assertNoRawMeasure(FILE_2_REF, DUPLICATED_BLOCKS_KEY);
+ assertRawMeasureValue(FILE_1_REF, DUPLICATED_BLOCKS_KEY, 1);
+ }
+
+ @Test
+ public void compute_duplicated_blocks_one_for_original_and_ignores_CrossProjectDuplicate() {
+ duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 1), SOME_FILE_KEY, new TextBlock(2, 2));
+
+ underTest.execute();
+
+ assertRawMeasureValue(FILE_1_REF, DUPLICATED_BLOCKS_KEY, 1);
+ }
+
+ @Test
+ public void compute_and_aggregate_duplicated_blocks_from_single_duplication() {
+ addDuplicatedBlock(FILE_1_REF, 10);
+ addDuplicatedBlock(FILE_2_REF, 40);
+ addDuplicatedBlock(FILE_4_REF, 5);
+
+ underTest.execute();
+
+ assertRawMeasureValue(FILE_1_REF, DUPLICATED_BLOCKS_KEY, 10);
+ assertRawMeasureValue(FILE_2_REF, DUPLICATED_BLOCKS_KEY, 40);
+ assertRawMeasureValue(FILE_3_REF, DUPLICATED_BLOCKS_KEY, 0);
+ assertRawMeasureValue(FILE_4_REF, DUPLICATED_BLOCKS_KEY, 5);
assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_BLOCKS_KEY, 50);
- assertRawMeasureValue(SUB_MODULE_REF, DUPLICATED_BLOCKS_KEY, 50);
- assertRawMeasureValue(MODULE_REF, DUPLICATED_BLOCKS_KEY, 50);
- assertRawMeasureValue(ROOT_REF, DUPLICATED_BLOCKS_KEY, 50);
+ assertRawMeasureValue(SUB_MODULE_1_REF, DUPLICATED_BLOCKS_KEY, 50);
+ assertRawMeasureValue(SUB_MODULE_2_REF, DUPLICATED_BLOCKS_KEY, 5);
+ assertRawMeasureValue(MODULE_REF, DUPLICATED_BLOCKS_KEY, 55);
+ assertRawMeasureValue(ROOT_REF, DUPLICATED_BLOCKS_KEY, 55);
}
@Test
- public void aggregate_zero_duplicated_blocks() {
- addRawMeasure(FILE_1_REF, DUPLICATED_BLOCKS_KEY, 0);
- addRawMeasure(FILE_2_REF, DUPLICATED_BLOCKS_KEY, 0);
+ public void compute_and_aggregate_duplicated_blocks_to_zero_when_no_duplication() {
+ underTest.execute();
+
+ assertComputedAndAggregatedToZeroInt(DUPLICATED_BLOCKS_KEY);
+ }
+
+ @Test
+ public void compute_duplicated_lines_counts_lines_from_original_and_InnerDuplicate_of_a_single_line() {
+ TextBlock original = new TextBlock(1, 1);
+ duplicationRepository.addDuplication(FILE_1_REF, original, new TextBlock(2, 2));
underTest.execute();
- assertNoRawMeasure(FILE_1_REF, DUPLICATED_BLOCKS_KEY);
- assertNoRawMeasure(FILE_2_REF, DUPLICATED_BLOCKS_KEY);
- assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_BLOCKS_KEY, 0);
- assertRawMeasureValue(SUB_MODULE_REF, DUPLICATED_BLOCKS_KEY, 0);
- assertRawMeasureValue(MODULE_REF, DUPLICATED_BLOCKS_KEY, 0);
- assertRawMeasureValue(ROOT_REF, DUPLICATED_BLOCKS_KEY, 0);
+ assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_KEY, 2);
}
@Test
- public void aggregate_zero_duplicated_blocks_when_no_data() {
+ public void compute_duplicated_lines_counts_lines_from_original_and_ignores_InProjectDuplicate() {
+ TextBlock original = new TextBlock(1, 1);
+ duplicationRepository.addDuplication(FILE_1_REF, original, FILE_2_REF, new TextBlock(2, 2));
+
underTest.execute();
- assertNoRawMeasure(FILE_1_REF, DUPLICATED_BLOCKS_KEY);
- assertNoRawMeasure(FILE_2_REF, DUPLICATED_BLOCKS_KEY);
- assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_BLOCKS_KEY, 0);
- assertRawMeasureValue(SUB_MODULE_REF, DUPLICATED_BLOCKS_KEY, 0);
- assertRawMeasureValue(MODULE_REF, DUPLICATED_BLOCKS_KEY, 0);
- assertRawMeasureValue(ROOT_REF, DUPLICATED_BLOCKS_KEY, 0);
+ assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_KEY, 1);
}
@Test
- public void aggregate_duplicated_files() {
- addRawMeasure(FILE_1_REF, DUPLICATED_FILES_KEY, 10);
- addRawMeasure(FILE_2_REF, DUPLICATED_FILES_KEY, 40);
+ public void compute_duplicated_lines_counts_lines_from_original_and_ignores_CrossProjectDuplicate() {
+ TextBlock original = new TextBlock(1, 1);
+ duplicationRepository.addDuplication(FILE_1_REF, original, SOME_FILE_KEY, new TextBlock(2, 2));
underTest.execute();
- assertNoRawMeasure(FILE_1_REF, DUPLICATED_FILES_KEY);
- assertNoRawMeasure(FILE_2_REF, DUPLICATED_FILES_KEY);
- assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_FILES_KEY, 50);
- assertRawMeasureValue(SUB_MODULE_REF, DUPLICATED_FILES_KEY, 50);
- assertRawMeasureValue(MODULE_REF, DUPLICATED_FILES_KEY, 50);
- assertRawMeasureValue(ROOT_REF, DUPLICATED_FILES_KEY, 50);
+ assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_KEY, 1);
}
@Test
- public void aggregate_zero_duplicated_files() {
- addRawMeasure(FILE_1_REF, DUPLICATED_FILES_KEY, 0);
- addRawMeasure(FILE_2_REF, DUPLICATED_FILES_KEY, 0);
+ public void compute_duplicated_lines_counts_lines_from_original_and_InnerDuplicate() {
+ TextBlock original = new TextBlock(1, 5);
+ duplicationRepository.addDuplication(FILE_1_REF, original, new TextBlock(10, 11));
underTest.execute();
- assertNoRawMeasure(FILE_1_REF, DUPLICATED_FILES_KEY);
- assertNoRawMeasure(FILE_2_REF, DUPLICATED_FILES_KEY);
- assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_FILES_KEY, 0);
- assertRawMeasureValue(SUB_MODULE_REF, DUPLICATED_FILES_KEY, 0);
- assertRawMeasureValue(MODULE_REF, DUPLICATED_FILES_KEY, 0);
- assertRawMeasureValue(ROOT_REF, DUPLICATED_FILES_KEY, 0);
+ assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_KEY, 7);
}
@Test
- public void aggregate_zero_duplicated_files_when_no_data() {
+ public void compute_duplicated_lines_counts_lines_from_original_and_InnerDuplicate_only_once() {
+ TextBlock original = new TextBlock(1, 12);
+ duplicationRepository.addDuplication(FILE_1_REF, original, new TextBlock(10, 11));
+ duplicationRepository.addDuplication(FILE_1_REF, original, new TextBlock(11, 15));
+ duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(2, 2), new TextBlock(96, 96));
+
underTest.execute();
- assertNoRawMeasure(FILE_1_REF, DUPLICATED_FILES_KEY);
- assertNoRawMeasure(FILE_2_REF, DUPLICATED_FILES_KEY);
- assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_FILES_KEY, 0);
- assertRawMeasureValue(SUB_MODULE_REF, DUPLICATED_FILES_KEY, 0);
- assertRawMeasureValue(MODULE_REF, DUPLICATED_FILES_KEY, 0);
- assertRawMeasureValue(ROOT_REF, DUPLICATED_FILES_KEY, 0);
+ assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_KEY, 16);
}
@Test
- public void aggregate_duplicated_lines() {
- addRawMeasure(FILE_1_REF, DUPLICATED_LINES_KEY, 10);
- addRawMeasure(FILE_2_REF, DUPLICATED_LINES_KEY, 40);
+ public void compute_and_aggregate_duplicated_files() {
+ addDuplicatedBlock(FILE_1_REF, 2);
+ addDuplicatedBlock(FILE_3_REF, 10);
+ addDuplicatedBlock(FILE_4_REF, 50);
underTest.execute();
- assertNoRawMeasure(FILE_1_REF, DUPLICATED_LINES_KEY);
- assertNoRawMeasure(FILE_2_REF, DUPLICATED_LINES_KEY);
- assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_LINES_KEY, 50);
- assertRawMeasureValue(SUB_MODULE_REF, DUPLICATED_LINES_KEY, 50);
- assertRawMeasureValue(MODULE_REF, DUPLICATED_LINES_KEY, 50);
- assertRawMeasureValue(ROOT_REF, DUPLICATED_LINES_KEY, 50);
+ assertRawMeasureValue(FILE_1_REF, DUPLICATED_FILES_KEY, 1);
+ assertRawMeasureValue(FILE_2_REF, DUPLICATED_FILES_KEY, 0);
+ assertRawMeasureValue(FILE_3_REF, DUPLICATED_FILES_KEY, 1);
+ assertRawMeasureValue(FILE_4_REF, DUPLICATED_FILES_KEY, 1);
+ assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_FILES_KEY, 1);
+ assertRawMeasureValue(SUB_MODULE_1_REF, DUPLICATED_FILES_KEY, 1);
+ assertRawMeasureValue(SUB_MODULE_2_REF, DUPLICATED_FILES_KEY, 2);
+ assertRawMeasureValue(MODULE_REF, DUPLICATED_FILES_KEY, 3);
+ assertRawMeasureValue(ROOT_REF, DUPLICATED_FILES_KEY, 3);
}
@Test
- public void aggregate_zero_duplicated_line() {
- addRawMeasure(FILE_1_REF, DUPLICATED_LINES_KEY, 0);
- addRawMeasure(FILE_2_REF, DUPLICATED_LINES_KEY, 0);
+ public void compute_and_aggregate_zero_duplicated_files_when_no_duplication_data() {
+ underTest.execute();
+
+ assertComputedAndAggregatedToZeroInt(DUPLICATED_FILES_KEY);
+ }
+
+ @Test
+ public void compute_and_aggregate_duplicated_lines() {
+ addDuplicatedBlock(FILE_1_REF, 10);
+ addDuplicatedBlock(FILE_2_REF, 9);
+ addDuplicatedBlock(FILE_4_REF, 7);
underTest.execute();
- assertNoRawMeasure(FILE_1_REF, DUPLICATED_LINES_KEY);
- assertNoRawMeasure(FILE_2_REF, DUPLICATED_LINES_KEY);
- assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_LINES_KEY, 0);
- assertRawMeasureValue(SUB_MODULE_REF, DUPLICATED_LINES_KEY, 0);
- assertRawMeasureValue(MODULE_REF, DUPLICATED_LINES_KEY, 0);
- assertRawMeasureValue(ROOT_REF, DUPLICATED_LINES_KEY, 0);
+ assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_KEY, 10);
+ assertRawMeasureValue(FILE_2_REF, DUPLICATED_LINES_KEY, 9);
+ assertRawMeasureValue(FILE_3_REF, DUPLICATED_LINES_KEY, 0);
+ assertRawMeasureValue(FILE_4_REF, DUPLICATED_LINES_KEY, 7);
+ assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_LINES_KEY, 19);
+ assertRawMeasureValue(SUB_MODULE_1_REF, DUPLICATED_LINES_KEY, 19);
+ assertRawMeasureValue(SUB_MODULE_2_REF, DUPLICATED_LINES_KEY, 7);
+ assertRawMeasureValue(MODULE_REF, DUPLICATED_LINES_KEY, 26);
+ assertRawMeasureValue(ROOT_REF, DUPLICATED_LINES_KEY, 26);
}
@Test
- public void aggregate_zero_duplicated_line_when_no_data() {
+ public void compute_and_aggregate_zero_duplicated_line_when_no_duplication() {
underTest.execute();
- assertNoRawMeasure(FILE_1_REF, DUPLICATED_LINES_KEY);
- assertNoRawMeasure(FILE_2_REF, DUPLICATED_LINES_KEY);
- assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_LINES_KEY, 0);
- assertRawMeasureValue(SUB_MODULE_REF, DUPLICATED_LINES_KEY, 0);
- assertRawMeasureValue(MODULE_REF, DUPLICATED_LINES_KEY, 0);
- assertRawMeasureValue(ROOT_REF, DUPLICATED_LINES_KEY, 0);
+ String metricKey = DUPLICATED_LINES_KEY;
+ assertComputedAndAggregatedToZeroInt(metricKey);
}
@Test
public void compute_and_aggregate_duplicated_lines_density_using_lines() throws Exception {
- addRawMeasure(FILE_1_REF, DUPLICATED_LINES_KEY, 2);
- addRawMeasure(FILE_2_REF, DUPLICATED_LINES_KEY, 3);
+ addDuplicatedBlock(FILE_1_REF, 2);
+ addDuplicatedBlock(FILE_2_REF, 3);
addRawMeasure(FILE_1_REF, LINES_KEY, 10);
addRawMeasure(FILE_2_REF, LINES_KEY, 40);
addRawMeasure(DIRECTORY_REF, LINES_KEY, 50);
- addRawMeasure(SUB_MODULE_REF, LINES_KEY, 50);
+ addRawMeasure(SUB_MODULE_1_REF, LINES_KEY, 50);
addRawMeasure(MODULE_REF, LINES_KEY, 50);
addRawMeasure(ROOT_REF, LINES_KEY, 50);
assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_DENSITY_KEY, 20d);
assertRawMeasureValue(FILE_2_REF, DUPLICATED_LINES_DENSITY_KEY, 7.5d);
+ assertNoRawMeasure(FILE_3_REF, DUPLICATED_LINES_DENSITY_KEY);
+ assertNoRawMeasure(FILE_4_REF, DUPLICATED_LINES_DENSITY_KEY);
assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
- assertRawMeasureValue(SUB_MODULE_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
+ assertRawMeasureValue(SUB_MODULE_1_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
+ assertNoRawMeasure(SUB_MODULE_2_REF, DUPLICATED_LINES_DENSITY_KEY);
assertRawMeasureValue(MODULE_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
assertRawMeasureValue(ROOT_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
}
@Test
public void compute_and_aggregate_duplicated_lines_density_using_nclocs_and_comment_lines() throws Exception {
- addRawMeasure(FILE_1_REF, DUPLICATED_LINES_KEY, 2);
- addRawMeasure(FILE_2_REF, DUPLICATED_LINES_KEY, 3);
+ addDuplicatedBlock(FILE_1_REF, 2);
+ addDuplicatedBlock(FILE_2_REF, 3);
addRawMeasure(FILE_1_REF, COMMENT_LINES_KEY, 2);
addRawMeasure(FILE_2_REF, COMMENT_LINES_KEY, 10);
addRawMeasure(DIRECTORY_REF, COMMENT_LINES_KEY, 12);
- addRawMeasure(SUB_MODULE_REF, COMMENT_LINES_KEY, 12);
+ addRawMeasure(SUB_MODULE_1_REF, COMMENT_LINES_KEY, 12);
addRawMeasure(MODULE_REF, COMMENT_LINES_KEY, 12);
addRawMeasure(ROOT_REF, COMMENT_LINES_KEY, 12);
addRawMeasure(FILE_1_REF, NCLOC_KEY, 8);
addRawMeasure(FILE_2_REF, NCLOC_KEY, 30);
addRawMeasure(DIRECTORY_REF, NCLOC_KEY, 38);
- addRawMeasure(SUB_MODULE_REF, NCLOC_KEY, 38);
+ addRawMeasure(SUB_MODULE_1_REF, NCLOC_KEY, 38);
addRawMeasure(MODULE_REF, NCLOC_KEY, 38);
addRawMeasure(ROOT_REF, NCLOC_KEY, 38);
assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_DENSITY_KEY, 20d);
assertRawMeasureValue(FILE_2_REF, DUPLICATED_LINES_DENSITY_KEY, 7.5d);
+ assertNoRawMeasure(FILE_3_REF, DUPLICATED_LINES_DENSITY_KEY);
+ assertNoRawMeasure(FILE_4_REF, DUPLICATED_LINES_DENSITY_KEY);
assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
- assertRawMeasureValue(SUB_MODULE_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
+ assertRawMeasureValue(SUB_MODULE_1_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
+ assertNoRawMeasure(SUB_MODULE_2_REF, DUPLICATED_LINES_DENSITY_KEY);
assertRawMeasureValue(MODULE_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
assertRawMeasureValue(ROOT_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
}
@Test
public void compute_duplicated_lines_density_using_only_nclocs() throws Exception {
- addRawMeasure(FILE_1_REF, DUPLICATED_LINES_KEY, 2);
- addRawMeasure(FILE_2_REF, DUPLICATED_LINES_KEY, 3);
+ addDuplicatedBlock(FILE_1_REF, 2);
+ addDuplicatedBlock(FILE_2_REF, 3);
addRawMeasure(FILE_1_REF, NCLOC_KEY, 10);
addRawMeasure(FILE_2_REF, NCLOC_KEY, 40);
addRawMeasure(DIRECTORY_REF, NCLOC_KEY, 50);
- addRawMeasure(SUB_MODULE_REF, NCLOC_KEY, 50);
+ addRawMeasure(SUB_MODULE_1_REF, NCLOC_KEY, 50);
addRawMeasure(MODULE_REF, NCLOC_KEY, 50);
addRawMeasure(ROOT_REF, NCLOC_KEY, 50);
assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_DENSITY_KEY, 20d);
assertRawMeasureValue(FILE_2_REF, DUPLICATED_LINES_DENSITY_KEY, 7.5d);
+ assertNoRawMeasure(FILE_3_REF, DUPLICATED_LINES_DENSITY_KEY);
+ assertNoRawMeasure(FILE_4_REF, DUPLICATED_LINES_DENSITY_KEY);
assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
- assertRawMeasureValue(SUB_MODULE_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
+ assertRawMeasureValue(SUB_MODULE_1_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
+ assertNoRawMeasure(SUB_MODULE_2_REF, DUPLICATED_LINES_DENSITY_KEY);
assertRawMeasureValue(MODULE_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
assertRawMeasureValue(ROOT_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
}
@Test
- public void compute_zero_percent_duplicated_lines_density_when_duplicated_lines_are_zero() throws Exception {
- addRawMeasure(FILE_1_REF, DUPLICATED_LINES_KEY, 0);
- addRawMeasure(FILE_2_REF, DUPLICATED_LINES_KEY, 0);
-
+ public void compute_zero_percent_duplicated_lines_density_when_there_is_no_duplication() throws Exception {
addRawMeasure(FILE_1_REF, COMMENT_LINES_KEY, 2);
addRawMeasure(FILE_2_REF, COMMENT_LINES_KEY, 10);
addRawMeasure(DIRECTORY_REF, COMMENT_LINES_KEY, 12);
- addRawMeasure(SUB_MODULE_REF, COMMENT_LINES_KEY, 12);
+ addRawMeasure(SUB_MODULE_1_REF, COMMENT_LINES_KEY, 12);
addRawMeasure(MODULE_REF, COMMENT_LINES_KEY, 12);
addRawMeasure(ROOT_REF, COMMENT_LINES_KEY, 12);
addRawMeasure(FILE_1_REF, NCLOC_KEY, 8);
addRawMeasure(FILE_2_REF, NCLOC_KEY, 30);
addRawMeasure(DIRECTORY_REF, NCLOC_KEY, 38);
- addRawMeasure(SUB_MODULE_REF, NCLOC_KEY, 38);
+ addRawMeasure(SUB_MODULE_1_REF, NCLOC_KEY, 38);
addRawMeasure(MODULE_REF, NCLOC_KEY, 38);
addRawMeasure(ROOT_REF, NCLOC_KEY, 38);
assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_DENSITY_KEY, 0d);
assertRawMeasureValue(FILE_2_REF, DUPLICATED_LINES_DENSITY_KEY, 0d);
+ assertNoRawMeasure(FILE_3_REF, DUPLICATED_LINES_DENSITY_KEY);
+ assertNoRawMeasure(FILE_4_REF, DUPLICATED_LINES_DENSITY_KEY);
assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_LINES_DENSITY_KEY, 0d);
- assertRawMeasureValue(SUB_MODULE_REF, DUPLICATED_LINES_DENSITY_KEY, 0d);
+ assertRawMeasureValue(SUB_MODULE_1_REF, DUPLICATED_LINES_DENSITY_KEY, 0d);
+ assertNoRawMeasure(SUB_MODULE_2_REF, DUPLICATED_LINES_DENSITY_KEY);
assertRawMeasureValue(MODULE_REF, DUPLICATED_LINES_DENSITY_KEY, 0d);
assertRawMeasureValue(ROOT_REF, DUPLICATED_LINES_DENSITY_KEY, 0d);
}
addRawMeasure(FILE_1_REF, LINES_KEY, 0);
addRawMeasure(FILE_2_REF, LINES_KEY, 0);
addRawMeasure(DIRECTORY_REF, LINES_KEY, 0);
- addRawMeasure(SUB_MODULE_REF, LINES_KEY, 0);
+ addRawMeasure(SUB_MODULE_1_REF, LINES_KEY, 0);
addRawMeasure(MODULE_REF, LINES_KEY, 0);
addRawMeasure(ROOT_REF, LINES_KEY, 0);
addRawMeasure(FILE_1_REF, COMMENT_LINES_KEY, 0);
addRawMeasure(FILE_2_REF, COMMENT_LINES_KEY, 0);
addRawMeasure(DIRECTORY_REF, COMMENT_LINES_KEY, 0);
- addRawMeasure(SUB_MODULE_REF, COMMENT_LINES_KEY, 0);
+ addRawMeasure(SUB_MODULE_1_REF, COMMENT_LINES_KEY, 0);
addRawMeasure(MODULE_REF, COMMENT_LINES_KEY, 0);
addRawMeasure(ROOT_REF, COMMENT_LINES_KEY, 0);
addRawMeasure(FILE_1_REF, NCLOC_KEY, 0);
addRawMeasure(FILE_2_REF, NCLOC_KEY, 0);
addRawMeasure(DIRECTORY_REF, NCLOC_KEY, 0);
- addRawMeasure(SUB_MODULE_REF, NCLOC_KEY, 0);
+ addRawMeasure(SUB_MODULE_1_REF, NCLOC_KEY, 0);
addRawMeasure(MODULE_REF, NCLOC_KEY, 0);
addRawMeasure(ROOT_REF, NCLOC_KEY, 0);
@Test
public void compute_100_percent_duplicated_lines_density() throws Exception {
- addRawMeasure(FILE_1_REF, DUPLICATED_LINES_KEY, 2);
- addRawMeasure(FILE_2_REF, DUPLICATED_LINES_KEY, 3);
+ addDuplicatedBlock(FILE_1_REF, 2);
+ addDuplicatedBlock(FILE_2_REF, 3);
addRawMeasure(FILE_1_REF, LINES_KEY, 2);
addRawMeasure(FILE_2_REF, LINES_KEY, 3);
addRawMeasure(DIRECTORY_REF, LINES_KEY, 5);
- addRawMeasure(SUB_MODULE_REF, LINES_KEY, 5);
+ addRawMeasure(SUB_MODULE_1_REF, LINES_KEY, 5);
addRawMeasure(MODULE_REF, LINES_KEY, 5);
addRawMeasure(ROOT_REF, LINES_KEY, 5);
assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_DENSITY_KEY, 100d);
assertRawMeasureValue(FILE_2_REF, DUPLICATED_LINES_DENSITY_KEY, 100d);
+ assertNoRawMeasure(FILE_3_REF, DUPLICATED_LINES_DENSITY_KEY);
+ assertNoRawMeasure(FILE_4_REF, DUPLICATED_LINES_DENSITY_KEY);
assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_LINES_DENSITY_KEY, 100d);
- assertRawMeasureValue(SUB_MODULE_REF, DUPLICATED_LINES_DENSITY_KEY, 100d);
+ assertRawMeasureValue(SUB_MODULE_1_REF, DUPLICATED_LINES_DENSITY_KEY, 100d);
+ assertNoRawMeasure(SUB_MODULE_2_REF, DUPLICATED_LINES_DENSITY_KEY);
assertRawMeasureValue(MODULE_REF, DUPLICATED_LINES_DENSITY_KEY, 100d);
assertRawMeasureValue(ROOT_REF, DUPLICATED_LINES_DENSITY_KEY, 100d);
}
+ /**
+ * Adds duplication blocks of a single line (each line is specific to its block).
+ *
+ * This is a very simple use case, convenient for unit tests but more realistic and complex use cases must be tested separately.
+ */
+ private void addDuplicatedBlock(int fileRef, int blockCount) {
+ checkArgument(blockCount > 1, "BlockCount can not be less than 2");
+ TextBlock original = new TextBlock(1, 1);
+ for (int i = 10; i < blockCount + 9; i++) {
+ duplicationRepository.addDuplication(fileRef, original, new TextBlock(i, i));
+ }
+ }
+
private void addRawMeasure(int componentRef, String metricKey, int value) {
measureRepository.addRawMeasure(componentRef, metricKey, newMeasureBuilder().create(value));
}
assertThat(measureRepository.getAddedRawMeasures(FILE_1_REF).get(metricKey)).isEmpty();
assertThat(measureRepository.getAddedRawMeasures(FILE_2_REF).get(metricKey)).isEmpty();
assertThat(measureRepository.getAddedRawMeasures(DIRECTORY_REF).get(metricKey)).isEmpty();
- assertThat(measureRepository.getAddedRawMeasures(SUB_MODULE_REF).get(metricKey)).isEmpty();
+ assertThat(measureRepository.getAddedRawMeasures(SUB_MODULE_1_REF).get(metricKey)).isEmpty();
assertThat(measureRepository.getAddedRawMeasures(MODULE_REF).get(metricKey)).isEmpty();
assertThat(measureRepository.getAddedRawMeasures(ROOT_REF).get(metricKey)).isEmpty();
}
assertThat(measureRepository.getAddedRawMeasure(componentRef, metricKey).get().getDoubleValue()).isEqualTo(value);
}
+ private void assertComputedAndAggregatedToZeroInt(String metricKey) {
+ assertRawMeasureValue(FILE_1_REF, metricKey, 0);
+ assertRawMeasureValue(FILE_2_REF, metricKey, 0);
+ assertRawMeasureValue(FILE_3_REF, metricKey, 0);
+ assertRawMeasureValue(FILE_4_REF, metricKey, 0);
+ assertRawMeasureValue(DIRECTORY_REF, metricKey, 0);
+ assertRawMeasureValue(SUB_MODULE_1_REF, metricKey, 0);
+ assertRawMeasureValue(SUB_MODULE_2_REF, metricKey, 0);
+ assertRawMeasureValue(MODULE_REF, metricKey, 0);
+ assertRawMeasureValue(ROOT_REF, metricKey, 0);
+ }
+
}