]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7012 Use standard persistence for duplications_data measure
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 12 Nov 2015 09:50:20 +0000 (10:50 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 12 Nov 2015 10:02:43 +0000 (11:02 +0100)
server/sonar-server/src/main/java/org/sonar/server/computation/step/DuplicationDataMeasuresStep.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistDuplicationsStep.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/step/ReportComputationSteps.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/DuplicationDataMeasuresStepTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistDuplicationsStepTest.java [deleted file]

diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/DuplicationDataMeasuresStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/DuplicationDataMeasuresStep.java
new file mode 100644 (file)
index 0000000..0fbe43f
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.computation.step;
+
+import java.util.Set;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.CrawlerDepthLimit;
+import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
+import org.sonar.server.computation.component.TreeRootHolder;
+import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
+import org.sonar.server.computation.duplication.CrossProjectDuplicate;
+import org.sonar.server.computation.duplication.Duplicate;
+import org.sonar.server.computation.duplication.Duplication;
+import org.sonar.server.computation.duplication.DuplicationRepository;
+import org.sonar.server.computation.duplication.InProjectDuplicate;
+import org.sonar.server.computation.duplication.InnerDuplicate;
+import org.sonar.server.computation.duplication.TextBlock;
+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 org.sonar.api.measures.CoreMetrics.DUPLICATIONS_DATA_KEY;
+import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
+
+/**
+ * Compute duplication data measures on files, based on the {@link DuplicationRepository}
+ */
+public class DuplicationDataMeasuresStep implements ComputationStep {
+
+  private final MeasureRepository measureRepository;
+  private final TreeRootHolder treeRootHolder;
+  private final DuplicationRepository duplicationRepository;
+
+  private final Metric duplicationDataMetric;
+
+  public DuplicationDataMeasuresStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository,
+    DuplicationRepository duplicationRepository) {
+    this.measureRepository = measureRepository;
+    this.treeRootHolder = treeRootHolder;
+    this.duplicationRepository = duplicationRepository;
+    this.duplicationDataMetric = metricRepository.getByKey(DUPLICATIONS_DATA_KEY);
+  }
+
+  @Override
+  public void execute() {
+    new DepthTraversalTypeAwareCrawler(new DuplicationVisitor())
+      .visit(treeRootHolder.getRoot());
+  }
+
+  private class DuplicationVisitor extends TypeAwareVisitorAdapter {
+
+    private DuplicationVisitor() {
+      super(CrawlerDepthLimit.FILE, PRE_ORDER);
+    }
+
+    @Override
+    public void visitFile(Component file) {
+      Set<Duplication> duplications = duplicationRepository.getDuplications(file);
+      if (!duplications.isEmpty()) {
+        computeDuplications(file, duplications);
+      }
+    }
+
+    private void computeDuplications(Component component, Iterable<Duplication> duplications) {
+      String duplicationXml = createXmlDuplications(component.getKey(), duplications);
+      measureRepository.add(
+        component,
+        duplicationDataMetric,
+        Measure.newMeasureBuilder().create(duplicationXml)
+        );
+    }
+
+    private String createXmlDuplications(String componentKey, Iterable<Duplication> duplications) {
+      StringBuilder xml = new StringBuilder();
+      xml.append("<duplications>");
+      for (Duplication duplication : duplications) {
+        xml.append("<g>");
+        appendDuplication(xml, componentKey, duplication.getOriginal());
+        for (Duplicate duplicate : duplication.getDuplicates()) {
+          processDuplicationBlock(xml, duplicate, componentKey);
+        }
+        xml.append("</g>");
+      }
+      xml.append("</duplications>");
+      return xml.toString();
+    }
+
+    private void processDuplicationBlock(StringBuilder xml, Duplicate duplicate, String componentKey) {
+      if (duplicate instanceof InnerDuplicate) {
+        // Duplication is on a the same file
+        appendDuplication(xml, componentKey, duplicate);
+      } else if (duplicate instanceof InProjectDuplicate) {
+        // Duplication is on a different file
+        appendDuplication(xml, ((InProjectDuplicate) duplicate).getFile().getKey(), duplicate);
+      } else if (duplicate instanceof CrossProjectDuplicate) {
+        // componentKey is only set for cross project duplications
+        String crossProjectComponentKey = ((CrossProjectDuplicate) duplicate).getFileKey();
+        appendDuplication(xml, crossProjectComponentKey, duplicate);
+      } else {
+        throw new IllegalArgumentException("Unsupported type of Duplicate " + duplicate.getClass().getName());
+      }
+    }
+
+    private void appendDuplication(StringBuilder xml, String componentKey, Duplicate duplicate) {
+      appendDuplication(xml, componentKey, duplicate.getTextBlock());
+    }
+
+    private void appendDuplication(StringBuilder xml, String componentKey, TextBlock textBlock) {
+      int length = textBlock.getEnd() - textBlock.getStart() + 1;
+      xml.append("<b s=\"").append(textBlock.getStart())
+        .append("\" l=\"").append(length)
+        .append("\" r=\"").append(StringEscapeUtils.escapeXml(componentKey))
+        .append("\"/>");
+    }
+  }
+
+  @Override
+  public String getDescription() {
+    return "Compute duplication data measures";
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistDuplicationsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistDuplicationsStep.java
deleted file mode 100644 (file)
index 901df0b..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.computation.step;
-
-import java.util.Set;
-import org.apache.commons.lang.StringEscapeUtils;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.MyBatis;
-import org.sonar.db.measure.MeasureDto;
-import org.sonar.db.metric.MetricDto;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.CrawlerDepthLimit;
-import org.sonar.server.computation.component.DbIdsRepository;
-import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
-import org.sonar.server.computation.component.TreeRootHolder;
-import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
-import org.sonar.server.computation.duplication.CrossProjectDuplicate;
-import org.sonar.server.computation.duplication.Duplicate;
-import org.sonar.server.computation.duplication.Duplication;
-import org.sonar.server.computation.duplication.DuplicationRepository;
-import org.sonar.server.computation.duplication.InProjectDuplicate;
-import org.sonar.server.computation.duplication.InnerDuplicate;
-import org.sonar.server.computation.duplication.TextBlock;
-
-import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
-
-/**
- * Persist duplications into
- */
-public class PersistDuplicationsStep implements ComputationStep {
-
-  private final DbClient dbClient;
-  private final DbIdsRepository dbIdsRepository;
-  private final TreeRootHolder treeRootHolder;
-  private final DuplicationRepository duplicationRepository;
-
-  public PersistDuplicationsStep(DbClient dbClient, DbIdsRepository dbIdsRepository, TreeRootHolder treeRootHolder,
-    DuplicationRepository duplicationRepository) {
-    this.dbClient = dbClient;
-    this.dbIdsRepository = dbIdsRepository;
-    this.treeRootHolder = treeRootHolder;
-    this.duplicationRepository = duplicationRepository;
-  }
-
-  @Override
-  public void execute() {
-    DbSession session = dbClient.openSession(true);
-    try {
-      MetricDto duplicationMetric = dbClient.metricDao().selectOrFailByKey(session, CoreMetrics.DUPLICATIONS_DATA_KEY);
-      new DepthTraversalTypeAwareCrawler(new DuplicationVisitor(session, duplicationMetric))
-        .visit(treeRootHolder.getRoot());
-      session.commit();
-    } finally {
-      MyBatis.closeQuietly(session);
-    }
-  }
-
-  private class DuplicationVisitor extends TypeAwareVisitorAdapter {
-
-    private final DbSession session;
-    private final MetricDto duplicationMetric;
-
-    private DuplicationVisitor(DbSession session, MetricDto duplicationMetric) {
-      super(CrawlerDepthLimit.FILE, PRE_ORDER);
-      this.session = session;
-      this.duplicationMetric = duplicationMetric;
-    }
-
-    @Override
-    public void visitFile(Component file) {
-      Set<Duplication> duplications = duplicationRepository.getDuplications(file);
-      if (!duplications.isEmpty()) {
-        saveDuplications(file, duplications);
-      }
-    }
-
-    private void saveDuplications(Component component, Iterable<Duplication> duplications) {
-      String duplicationXml = createXmlDuplications(component.getKey(), duplications);
-      MeasureDto measureDto = new MeasureDto()
-        .setMetricId(duplicationMetric.getId())
-        .setData(duplicationXml)
-        .setComponentId(dbIdsRepository.getComponentId(component))
-        .setSnapshotId(dbIdsRepository.getSnapshotId(component));
-      dbClient.measureDao().insert(session, measureDto);
-    }
-
-    private String createXmlDuplications(String componentKey, Iterable<Duplication> duplications) {
-      StringBuilder xml = new StringBuilder();
-      xml.append("<duplications>");
-      for (Duplication duplication : duplications) {
-        xml.append("<g>");
-        appendDuplication(xml, componentKey, duplication.getOriginal());
-        for (Duplicate duplicate : duplication.getDuplicates()) {
-          processDuplicationBlock(xml, duplicate, componentKey);
-        }
-        xml.append("</g>");
-      }
-      xml.append("</duplications>");
-      return xml.toString();
-    }
-
-    private void processDuplicationBlock(StringBuilder xml, Duplicate duplicate, String componentKey) {
-      if (duplicate instanceof InnerDuplicate) {
-        // Duplication is on a the same file
-        appendDuplication(xml, componentKey, duplicate);
-      } else if (duplicate instanceof InProjectDuplicate) {
-        // Duplication is on a different file
-        appendDuplication(xml, ((InProjectDuplicate) duplicate).getFile().getKey(), duplicate);
-      } else if (duplicate instanceof CrossProjectDuplicate) {
-        // componentKey is only set for cross project duplications
-        String crossProjectComponentKey = ((CrossProjectDuplicate) duplicate).getFileKey();
-        appendDuplication(xml, crossProjectComponentKey, duplicate);
-      } else {
-        throw new IllegalArgumentException("Unsupported type of Duplicate " + duplicate.getClass().getName());
-      }
-    }
-
-    private void appendDuplication(StringBuilder xml, String componentKey, Duplicate duplicate) {
-      appendDuplication(xml, componentKey, duplicate.getTextBlock());
-    }
-
-    private void appendDuplication(StringBuilder xml, String componentKey, TextBlock textBlock) {
-      int length = textBlock.getEnd() - textBlock.getStart() + 1;
-      xml.append("<b s=\"").append(textBlock.getStart())
-        .append("\" l=\"").append(length)
-        .append("\" r=\"").append(StringEscapeUtils.escapeXml(componentKey))
-        .append("\"/>");
-    }
-  }
-
-  @Override
-  public String getDescription() {
-    return "Persist duplications";
-  }
-
-}
index 8d4c2f5cd91367cd9f98082f11033580ead3e590..c9494f65379dd3aa44ce22cba542bb7693450ef4 100644 (file)
@@ -53,6 +53,8 @@ public class ReportComputationSteps implements ComputationSteps {
       LoadQualityGateStep.class,
       LoadPeriodsStep.class,
 
+      // load duplications related stuff
+      LoadDuplicationsFromReportStep.class,
       LoadCrossProjectDuplicationsRepositoryStep.class,
 
       // data computation
@@ -61,8 +63,8 @@ public class ReportComputationSteps implements ComputationSteps {
       CoverageMeasuresStep.class,
       CommentMeasuresStep.class,
       CustomMeasuresCopyStep.class,
-      LoadDuplicationsFromReportStep.class,
       DuplicationMeasuresStep.class,
+      DuplicationDataMeasuresStep.class,
       LanguageDistributionMeasuresStep.class,
       UnitTestMeasuresStep.class,
       ComplexityMeasuresStep.class,
@@ -89,7 +91,6 @@ public class ReportComputationSteps implements ComputationSteps {
       PersistIssuesStep.class,
       PersistProjectLinksStep.class,
       PersistEventsStep.class,
-      PersistDuplicationsStep.class,
       PersistFileSourcesStep.class,
       PersistTestsStep.class,
       PersistCrossProjectDuplicationIndexStep.class,
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/DuplicationDataMeasuresStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/DuplicationDataMeasuresStepTest.java
new file mode 100644 (file)
index 0000000..31cd2cf
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+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 org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.guava.api.Assertions.assertThat;
+import static org.sonar.api.measures.CoreMetrics.DUPLICATIONS_DATA;
+import static org.sonar.api.measures.CoreMetrics.DUPLICATIONS_DATA_KEY;
+import static org.sonar.server.computation.component.Component.Type.FILE;
+import static org.sonar.server.computation.component.Component.Type.PROJECT;
+import static org.sonar.server.computation.component.ReportComponent.builder;
+
+public class DuplicationDataMeasuresStepTest extends BaseStepTest {
+
+  private static final int ROOT_REF = 1;
+  private static final String PROJECT_KEY = "PROJECT_KEY";
+
+  private static final int FILE_1_REF = 2;
+  private static final String FILE_1_KEY = "FILE_1_KEY";
+
+  private static final int FILE_2_REF = 3;
+  private static final String FILE_2_KEY = "FILE_2_KEY";
+
+  @Rule
+  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule()
+    .setRoot(
+    builder(PROJECT, ROOT_REF).setKey(PROJECT_KEY)
+      .addChildren(
+        builder(FILE, FILE_1_REF).setKey(FILE_1_KEY)
+          .build(),
+        builder(FILE, FILE_2_REF).setKey(FILE_2_KEY)
+          .build())
+      .build());
+
+  @Rule
+  public DuplicationRepositoryRule duplicationRepository = DuplicationRepositoryRule.create(treeRootHolder);
+
+  @Rule
+  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
+    .add(DUPLICATIONS_DATA);
+
+  @Rule
+  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+
+  DuplicationDataMeasuresStep underTest = new DuplicationDataMeasuresStep(treeRootHolder, metricRepository, measureRepository, duplicationRepository);
+
+  @Override
+  protected ComputationStep step() {
+    return underTest;
+  }
+
+  @Test
+  public void nothing_to_do_when_no_duplication() {
+    underTest.execute();
+
+    assertThat(measureRepository.getAddedRawMeasure(FILE_1_REF, DUPLICATIONS_DATA_KEY)).isAbsent();
+    assertThat(measureRepository.getAddedRawMeasure(FILE_2_REF, DUPLICATIONS_DATA_KEY)).isAbsent();
+  }
+
+  @Test
+  public void compute_duplications_on_same_file() {
+    duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 5), new TextBlock(6, 10));
+
+    underTest.execute();
+
+    assertThat(measureRepository.getAddedRawMeasure(FILE_1_REF, DUPLICATIONS_DATA_KEY)).isPresent();
+    assertThat(measureRepository.getAddedRawMeasure(FILE_1_REF, DUPLICATIONS_DATA_KEY).get().getData()).isEqualTo(
+      "<duplications><g><b s=\"1\" l=\"5\" r=\"" + FILE_1_KEY + "\"/><b s=\"6\" l=\"5\" r=\"" + FILE_1_KEY + "\"/></g></duplications>"
+      );
+    assertThat(measureRepository.getAddedRawMeasure(FILE_2_REF, DUPLICATIONS_DATA_KEY)).isAbsent();
+  }
+
+  @Test
+  public void compute_duplications_on_different_files() {
+    duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 5), FILE_2_REF, new TextBlock(6, 10));
+
+    underTest.execute();
+
+    assertThat(measureRepository.getAddedRawMeasure(FILE_1_REF, DUPLICATIONS_DATA_KEY)).isPresent();
+    assertThat(measureRepository.getAddedRawMeasure(FILE_1_REF, DUPLICATIONS_DATA_KEY).get().getData()).isEqualTo(
+      "<duplications><g><b s=\"1\" l=\"5\" r=\"" + FILE_1_KEY + "\"/><b s=\"6\" l=\"5\" r=\"" + FILE_2_KEY + "\"/></g></duplications>"
+      );
+    assertThat(measureRepository.getAddedRawMeasure(FILE_2_REF, DUPLICATIONS_DATA_KEY)).isAbsent();
+  }
+
+  @Test
+  public void compute_duplications_on_different_projects() {
+    String fileKeyFromOtherProject = "PROJECT2_KEY:file2";
+    duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 5), fileKeyFromOtherProject, new TextBlock(6, 10));
+
+    underTest.execute();
+
+    assertThat(measureRepository.getAddedRawMeasure(FILE_1_REF, DUPLICATIONS_DATA_KEY)).isPresent();
+    assertThat(measureRepository.getAddedRawMeasure(FILE_1_REF, DUPLICATIONS_DATA_KEY).get().getData()).isEqualTo(
+      "<duplications><g><b s=\"1\" l=\"5\" r=\"" + FILE_1_KEY + "\"/><b s=\"6\" l=\"5\" r=\"" + fileKeyFromOtherProject + "\"/></g></duplications>"
+      );
+    assertThat(measureRepository.getAddedRawMeasure(FILE_2_REF, DUPLICATIONS_DATA_KEY)).isAbsent();
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistDuplicationsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistDuplicationsStepTest.java
deleted file mode 100644 (file)
index 7b004b1..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.computation.step;
-
-import java.util.Map;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.metric.MetricDto;
-import org.sonar.server.computation.batch.TreeRootHolderRule;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.DbIdsRepositoryImpl;
-import org.sonar.server.computation.component.ReportComponent;
-import org.sonar.server.computation.duplication.DuplicationRepositoryRule;
-import org.sonar.server.computation.duplication.TextBlock;
-import org.sonar.test.DbTests;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-@Category(DbTests.class)
-public class PersistDuplicationsStepTest extends BaseStepTest {
-
-  private static final String PROJECT_KEY = "PROJECT_KEY";
-  private static final int FILE_1_REF = 2;
-  private static final int FILE_2_REF = 3;
-  private static final int ROOT_REF = 1;
-
-  @Rule
-  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
-  @Rule
-  public DbTester dbTester = DbTester.create(System2.INSTANCE);
-  @Rule
-  public DuplicationRepositoryRule duplicationRepository = DuplicationRepositoryRule.create(treeRootHolder);
-
-  DbIdsRepositoryImpl dbIdsRepository = new DbIdsRepositoryImpl();
-  DbSession session = dbTester.getSession();
-  DbClient dbClient = dbTester.getDbClient();
-
-  PersistDuplicationsStep underTest;
-
-  @Before
-  public void setup() {
-    dbTester.truncateTables();
-    underTest = new PersistDuplicationsStep(dbClient, dbIdsRepository, treeRootHolder, duplicationRepository);
-  }
-
-  @Override
-  protected ComputationStep step() {
-    return underTest;
-  }
-
-  @After
-  public void tearDown() {
-    session.close();
-  }
-
-  @Test
-  public void nothing_to_do_when_no_duplication() {
-    saveDuplicationMetric();
-    initReportWithProjectAndFile();
-
-    underTest.execute();
-
-    assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(0);
-  }
-
-  @Test
-  public void persist_duplications_on_same_file() {
-    MetricDto duplicationMetric = saveDuplicationMetric();
-    initReportWithProjectAndFile();
-
-    duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 5), new TextBlock(6, 10));
-
-    underTest.execute();
-
-    assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(1);
-
-    Map<String, Object> dto = dbTester.selectFirst("select snapshot_id as \"snapshotId\", metric_id as \"metricId\", text_value as \"textValue\" from project_measures");
-    assertThat(dto.get("snapshotId")).isEqualTo(11L);
-    assertThat(dto.get("metricId")).isEqualTo(duplicationMetric.getId().longValue());
-    assertThat(dto.get("textValue")).isEqualTo("<duplications><g><b s=\"1\" l=\"5\" r=\"PROJECT_KEY:file\"/><b s=\"6\" l=\"5\" r=\"PROJECT_KEY:file\"/></g></duplications>");
-  }
-
-  @Test
-  public void persist_duplications_on_different_files() {
-    saveDuplicationMetric();
-    initReportWithProjectAndFile();
-
-    duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 5), 3, new TextBlock(6, 10));
-
-    underTest.execute();
-
-    assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(1);
-
-    Map<String, Object> dto = dbTester.selectFirst("select snapshot_id as \"snapshotId\", text_value as \"textValue\" from project_measures");
-    assertThat(dto.get("snapshotId")).isEqualTo(11L);
-    assertThat(dto.get("textValue")).isEqualTo("<duplications><g><b s=\"1\" l=\"5\" r=\"PROJECT_KEY:file\"/><b s=\"6\" l=\"5\" r=\"PROJECT_KEY:file2\"/></g></duplications>");
-  }
-
-  @Test
-  public void persist_duplications_on_different_projects() {
-    saveDuplicationMetric();
-    initReportWithProjectAndFile();
-
-    duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 5), "PROJECT2_KEY:file2", new TextBlock(6, 10));
-
-    underTest.execute();
-
-    assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(1);
-
-    Map<String, Object> dto = dbTester.selectFirst("select snapshot_id as \"snapshotId\", text_value as \"textValue\" from project_measures");
-    assertThat(dto.get("snapshotId")).isEqualTo(11L);
-    assertThat(dto.get("textValue")).isEqualTo("<duplications><g><b s=\"1\" l=\"5\" r=\"PROJECT_KEY:file\"/><b s=\"6\" l=\"5\" r=\"PROJECT2_KEY:file2\"/></g></duplications>");
-  }
-
-  private void initReportWithProjectAndFile() {
-    Component file1 = ReportComponent.builder(Component.Type.FILE, FILE_1_REF).setUuid("BCDE").setKey("PROJECT_KEY:file").build();
-    Component file2 = ReportComponent.builder(Component.Type.FILE, FILE_2_REF).setUuid("CDEF").setKey("PROJECT_KEY:file2").build();
-    Component project = ReportComponent.builder(Component.Type.PROJECT, ROOT_REF).setUuid("ABCD").setKey(PROJECT_KEY).addChildren(file1, file2).build();
-    treeRootHolder.setRoot(project);
-
-    dbIdsRepository.setComponentId(project, 1);
-    dbIdsRepository.setSnapshotId(project, 10);
-    dbIdsRepository.setComponentId(file1, 2);
-    dbIdsRepository.setSnapshotId(file1, 11);
-    dbIdsRepository.setComponentId(file2, 2);
-    dbIdsRepository.setSnapshotId(file2, 12);
-  }
-
-  private MetricDto saveDuplicationMetric() {
-    MetricDto duplicationMetric = new MetricDto().setKey(CoreMetrics.DUPLICATIONS_DATA_KEY)
-        .setOptimizedBestValue(false)
-        .setDeleteHistoricalData(false)
-        .setHidden(false);
-    dbClient.metricDao().insert(session, duplicationMetric);
-    session.commit();
-    return duplicationMetric;
-  }
-
-}