]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6991 compute all duplicate_* measure in CE
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 9 Nov 2015 15:33:42 +0000 (16:33 +0100)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Tue, 10 Nov 2015 15:35:57 +0000 (16:35 +0100)
duplicated_files, duplicated_blocks and duplicated_lines are now ignored when present in analysis report

server/sonar-server/src/main/java/org/sonar/server/computation/step/DuplicationMeasuresStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/ReportComputationSteps.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportDuplicationMeasuresStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsDuplicationMeasuresStepTest.java

index b9e12564d2650e1b47ce28d656b795cdc9257261..2d60d64a37b5fd4a93139b6a5b6ff1b81263a973 100644 (file)
@@ -22,21 +22,29 @@ package org.sonar.server.computation.step;
 
 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;
@@ -59,63 +67,149 @@ public class DuplicationMeasuresStep implements ComputationStep {
   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();
     }
@@ -136,67 +230,7 @@ public class DuplicationMeasuresStep implements ComputationStep {
 
     @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";
-  }
 }
index 067fd2f44ccb0005599e0a608cc26e11c0a4868e..3750a67e129229505fffd53515e73be2d053615c 100644 (file)
@@ -58,6 +58,7 @@ public class ReportComputationSteps implements ComputationSteps {
       CoverageMeasuresStep.class,
       CommentMeasuresStep.class,
       CustomMeasuresCopyStep.class,
+      LoadDuplicationsFromReportStep.class,
       DuplicationMeasuresStep.class,
       LanguageDistributionMeasuresStep.class,
       UnitTestMeasuresStep.class,
@@ -85,7 +86,6 @@ public class ReportComputationSteps implements ComputationSteps {
       PersistIssuesStep.class,
       PersistProjectLinksStep.class,
       PersistEventsStep.class,
-      LoadDuplicationsFromReportStep.class,
       PersistDuplicationsStep.class,
       PersistFileSourcesStep.class,
       PersistTestsStep.class,
index d54c75ed33e8b6a59dcaba1dffaaac1ed6e6c1a7..05f4ca5ffebd13e59c25d37b4f9f820c6aabe37c 100644 (file)
@@ -23,9 +23,12 @@ package org.sonar.server.computation.step;
 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;
@@ -53,10 +56,14 @@ public class ReportDuplicationMeasuresStepTest {
 
   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()
@@ -65,13 +72,19 @@ public class ReportDuplicationMeasuresStepTest {
       .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());
@@ -86,144 +99,191 @@ public class ReportDuplicationMeasuresStepTest {
     .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);
 
@@ -231,28 +291,31 @@ public class ReportDuplicationMeasuresStepTest {
 
     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);
 
@@ -260,21 +323,24 @@ public class ReportDuplicationMeasuresStepTest {
 
     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);
 
@@ -282,28 +348,28 @@ public class ReportDuplicationMeasuresStepTest {
 
     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);
 
@@ -311,8 +377,11 @@ public class ReportDuplicationMeasuresStepTest {
 
     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);
   }
@@ -322,7 +391,7 @@ public class ReportDuplicationMeasuresStepTest {
     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);
 
@@ -336,14 +405,14 @@ public class ReportDuplicationMeasuresStepTest {
     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);
 
@@ -354,13 +423,13 @@ public class ReportDuplicationMeasuresStepTest {
 
   @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);
 
@@ -368,12 +437,28 @@ public class ReportDuplicationMeasuresStepTest {
 
     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));
   }
@@ -382,7 +467,7 @@ public class ReportDuplicationMeasuresStepTest {
     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();
   }
@@ -399,4 +484,16 @@ public class ReportDuplicationMeasuresStepTest {
     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);
+  }
+
 }
index 64dd85ba8f37e08c7ae75eb39870c638c83e85f4..e0d626ef3dada3f59f4a958d60dd6c42f3e428e8 100644 (file)
@@ -60,15 +60,15 @@ public class ViewsDuplicationMeasuresStepTest {
   public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule()
     .setRoot(builder(VIEW, ROOT_REF)
       .addChildren(
-          builder(SUBVIEW, SUBVIEW_REF)
+        builder(SUBVIEW, SUBVIEW_REF)
+          .addChildren(
+            builder(SUBVIEW, SUB_SUBVIEW_REF)
               .addChildren(
-                  builder(SUBVIEW, SUB_SUBVIEW_REF)
-                      .addChildren(
-                          builder(PROJECT_VIEW, PROJECT_VIEW_1_REF).build(),
-                          builder(PROJECT_VIEW, PROJECT_VIEW_2_REF).build())
-                      .build())
-              .build(),
-          builder(PROJECT_VIEW, PROJECT_VIEW_3_REF).build())
+                builder(PROJECT_VIEW, PROJECT_VIEW_1_REF).build(),
+                builder(PROJECT_VIEW, PROJECT_VIEW_2_REF).build())
+              .build())
+          .build(),
+        builder(PROJECT_VIEW, PROJECT_VIEW_3_REF).build())
       .build());
   @Rule
   public MetricRepositoryRule metricRepository = new MetricRepositoryRule()