]> source.dussan.org Git - sonarqube.git/commitdiff
FillMeasuresWithVariationsStep now support Views Component tree
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Wed, 26 Aug 2015 09:05:10 +0000 (11:05 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Sat, 29 Aug 2015 13:58:41 +0000 (15:58 +0200)
server/sonar-server/src/main/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStep.java
server/sonar-server/src/test/java/org/sonar/server/component/SnapshotTesting.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStepTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportFillMeasuresWithVariationsStepTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsFillMeasuresWithVariationsStepTest.java [new file with mode: 0644]

index deef21ce0eb4eeff51ce385a07f85f6417379d51..ff51847f7bd99fc6e8d9210517f44c3265917986 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.server.computation.step;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
@@ -48,6 +47,9 @@ import org.sonar.server.computation.metric.MetricRepository;
 import org.sonar.server.computation.period.Period;
 import org.sonar.server.computation.period.PeriodsHolder;
 
+import static com.google.common.collect.FluentIterable.from;
+import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
+import static org.sonar.server.computation.component.Component.Type.SUBVIEW;
 import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
 
 /**
@@ -86,11 +88,11 @@ public class FillMeasuresWithVariationsStep implements ComputationStep {
   public void execute() {
     DbSession dbSession = dbClient.openSession(false);
     try {
-      Iterable<Metric> metrics = FluentIterable.from(metricRepository.getAll()).filter(NumericMetric.INSTANCE);
+      List<Metric> metrics = from(metricRepository.getAll()).filter(NumericMetric.INSTANCE).toList();
       new DepthTraversalTypeAwareCrawler(new VariationMeasuresVisitor(dbSession, metrics))
         .visit(treeRootHolder.getRoot());
     } finally {
-      dbSession.close();
+      dbClient.closeSession(dbSession);
     }
   }
 
@@ -102,10 +104,10 @@ public class FillMeasuresWithVariationsStep implements ComputationStep {
 
     public VariationMeasuresVisitor(DbSession session, Iterable<Metric> metrics) {
       // measures on files are currently purged, so past measures are not available on files
-      super(CrawlerDepthLimit.DIRECTORY, PRE_ORDER);
+      super(CrawlerDepthLimit.reportMaxDepth(DIRECTORY).withViewsMaxDepth(SUBVIEW), PRE_ORDER);
       this.session = session;
-      this.metricIds = FluentIterable.from(metrics).transform(MetricDtoToMetricId.INSTANCE).toSet();
-      this.metricByKeys = FluentIterable.from(metrics).uniqueIndex(MetricToKey.INSTANCE);
+      this.metricIds = from(metrics).transform(MetricDtoToMetricId.INSTANCE).toSet();
+      this.metricByKeys = from(metrics).uniqueIndex(MetricToKey.INSTANCE);
     }
 
     @Override
@@ -117,8 +119,8 @@ public class FillMeasuresWithVariationsStep implements ComputationStep {
     private MeasuresWithVariationRepository computeMeasuresWithVariations(Component component) {
       MeasuresWithVariationRepository measuresWithVariationRepository = new MeasuresWithVariationRepository();
       for (Period period : periodsHolder.getPeriods()) {
-        List<PastMeasureDto> pastMeasures = dbClient.measureDao().selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, component.getUuid(), period.getSnapshotId(),
-          metricIds);
+        List<PastMeasureDto> pastMeasures = dbClient.measureDao()
+          .selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, component.getUuid(), period.getSnapshotId(), metricIds);
         setVariationMeasures(component, pastMeasures, period.getIndex(), measuresWithVariationRepository);
       }
       return measuresWithVariationRepository;
@@ -140,7 +142,7 @@ public class FillMeasuresWithVariationsStep implements ComputationStep {
     }
 
     private void setVariationMeasures(Component component, List<PastMeasureDto> pastMeasures, int period, MeasuresWithVariationRepository measuresWithVariationRepository) {
-      Map<MeasureKey, PastMeasureDto> pastMeasuresByMeasureKey = FluentIterable.from(pastMeasures).uniqueIndex(pastMeasureToMeasureKey);
+      Map<MeasureKey, PastMeasureDto> pastMeasuresByMeasureKey = from(pastMeasures).uniqueIndex(pastMeasureToMeasureKey);
       for (Map.Entry<String, Measure> entry : measureRepository.getRawMeasures(component).entries()) {
         String metricKey = entry.getKey();
         Measure measure = entry.getValue();
index 738c7b5924daabe04621067fc93bc40d61ab66ec..e37007386a34e3b15c63799bc24b524c4ca18122 100644 (file)
@@ -41,7 +41,12 @@ public class SnapshotTesting {
 
   public static SnapshotDto createForProject(ComponentDto project) {
     return createBasicSnapshot(project, project.getId())
-      .setPath("");
+        .setPath("");
+  }
+
+  public static SnapshotDto createForView(ComponentDto view) {
+    return createBasicSnapshot(view, view.getId())
+        .setPath("");
   }
 
   private static SnapshotDto createBasicSnapshot(ComponentDto component, Long rootProjectId) {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStepTest.java
deleted file mode 100644 (file)
index e90819a..0000000
+++ /dev/null
@@ -1,240 +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 org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-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.component.ComponentDto;
-import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.measure.MeasureDto;
-import org.sonar.db.component.ComponentTesting;
-import org.sonar.server.computation.batch.BatchReportReaderRule;
-import org.sonar.server.computation.batch.TreeRootHolderRule;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.ReportComponent;
-import org.sonar.server.computation.measure.Measure;
-import org.sonar.server.computation.measure.MeasureRepositoryRule;
-import org.sonar.server.computation.metric.Metric;
-import org.sonar.server.computation.metric.MetricImpl;
-import org.sonar.server.computation.metric.MetricRepositoryRule;
-import org.sonar.server.computation.period.Period;
-import org.sonar.server.computation.period.PeriodsHolderRule;
-import org.sonar.test.DbTests;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.server.component.SnapshotTesting.createForComponent;
-import static org.sonar.server.component.SnapshotTesting.createForProject;
-
-@Category(DbTests.class)
-public class FillMeasuresWithVariationsStepTest {
-
-  static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT);
-  static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR);
-  static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT);
-  static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL);
-
-  static final ComponentDto PROJECT_DTO = ComponentTesting.newProjectDto();
-
-  static final Component PROJECT = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).build();
-
-  @Rule
-  public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
-  @Rule
-  public BatchReportReaderRule reportReader = new BatchReportReaderRule();
-
-  @Rule
-  public PeriodsHolderRule periodsHolder = new PeriodsHolderRule();
-
-  @Rule
-  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
-
-  @Rule
-  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
-    .add(ISSUES_METRIC)
-    .add(DEBT_METRIC)
-    .add(FILE_COMPLEXITY_METRIC)
-    .add(BUILD_BREAKER_METRIC);
-
-  @Rule
-  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
-
-  DbSession session = dbTester.getSession();
-
-  DbClient dbClient = dbTester.getDbClient();
-
-  FillMeasuresWithVariationsStep underTest;
-
-  @Before
-  public void setUp() {
-    dbTester.truncateTables();
-    dbClient.componentDao().insert(session, PROJECT_DTO);
-    session.commit();
-
-    underTest = new FillMeasuresWithVariationsStep(dbClient, treeRootHolder, periodsHolder, metricRepository, measureRepository);
-  }
-
-  @Test
-  public void do_nothing_when_no_raw_measure() {
-    SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
-    dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
-    session.commit();
-
-    periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
-
-    treeRootHolder.setRoot(PROJECT);
-
-    underTest.execute();
-
-    assertThat(measureRepository.getRawMeasures(PROJECT).keys()).isEmpty();
-  }
-
-  @Test
-  public void do_nothing_when_no_period() {
-    Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).build();
-    treeRootHolder.setRoot(project);
-    periodsHolder.setPeriods();
-
-    underTest.execute();
-
-    assertThat(measureRepository.getRawMeasures(project).keys()).isEmpty();
-  }
-
-  @Test
-  public void set_variation() {
-    // Project
-    SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
-    dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
-
-    // Directory
-    ComponentDto directoryDto = ComponentTesting.newDirectory(PROJECT_DTO, "dir");
-    dbClient.componentDao().insert(session, directoryDto);
-    SnapshotDto period1DirectorySnapshot = createForComponent(directoryDto, period1ProjectSnapshot);
-    dbClient.snapshotDao().insert(session, period1DirectorySnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), directoryDto.getId(), period1DirectorySnapshot.getId(), 10d));
-    session.commit();
-
-    periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
-
-    Component directory = ReportComponent.builder(Component.Type.DIRECTORY, 2).setUuid(directoryDto.uuid()).build();
-    Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).addChildren(directory).build();
-    treeRootHolder.setRoot(project);
-
-    addRawMeasure(project, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
-    addRawMeasure(directory, ISSUES_METRIC, Measure.newMeasureBuilder().create(20, null));
-
-    underTest.execute();
-
-    assertThat(measureRepository.getRawMeasure(project, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
-    assertThat(measureRepository.getRawMeasure(directory, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(10d);
-  }
-
-  @Test
-  public void set_variations_on_all_periods() {
-    SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
-    SnapshotDto period2ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
-    SnapshotDto period3ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
-    SnapshotDto period4ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
-    SnapshotDto period5ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
-    dbClient.snapshotDao().insert(session, period1ProjectSnapshot, period2ProjectSnapshot, period3ProjectSnapshot, period4ProjectSnapshot, period5ProjectSnapshot);
-
-    dbClient.measureDao().insert(session,
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 0d),
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period2ProjectSnapshot.getId(), 20d),
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period3ProjectSnapshot.getId(), 40d),
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period4ProjectSnapshot.getId(), 80d),
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period5ProjectSnapshot.getId(), 100d));
-    session.commit();
-
-    periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot),
-      newPeriod(2, period2ProjectSnapshot),
-      newPeriod(3, period3ProjectSnapshot),
-      newPeriod(4, period4ProjectSnapshot),
-      newPeriod(5, period5ProjectSnapshot));
-
-    treeRootHolder.setRoot(PROJECT);
-
-    addRawMeasure(PROJECT, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
-
-    underTest.execute();
-
-    assertThat(measureRepository.getRawMeasures(PROJECT).keys()).hasSize(1);
-
-    Measure measure = measureRepository.getRawMeasure(PROJECT, ISSUES_METRIC).get();
-    assertThat(measure.hasVariations()).isTrue();
-    assertThat(measure.getVariations().getVariation1()).isEqualTo(80d);
-    assertThat(measure.getVariations().getVariation2()).isEqualTo(60d);
-    assertThat(measure.getVariations().getVariation3()).isEqualTo(40d);
-    assertThat(measure.getVariations().getVariation4()).isEqualTo(0d);
-    assertThat(measure.getVariations().getVariation5()).isEqualTo(-20d);
-  }
-
-  @Test
-  public void set_variation_on_all_numeric_metrics() {
-    SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
-    dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
-    dbClient.measureDao().insert(session,
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d),
-      newMeasureDto(DEBT_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 10d),
-      newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 2d),
-      newMeasureDto(BUILD_BREAKER_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 1d)
-    );
-    session.commit();
-
-    periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
-
-    treeRootHolder.setRoot(PROJECT);
-
-    addRawMeasure(PROJECT, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
-    addRawMeasure(PROJECT, DEBT_METRIC, Measure.newMeasureBuilder().create(5L, null));
-    addRawMeasure(PROJECT, FILE_COMPLEXITY_METRIC, Measure.newMeasureBuilder().create(3d, null));
-    addRawMeasure(PROJECT, BUILD_BREAKER_METRIC, Measure.newMeasureBuilder().create(false, null));
-
-    underTest.execute();
-
-    assertThat(measureRepository.getRawMeasures(PROJECT).keys()).hasSize(4);
-
-    assertThat(measureRepository.getRawMeasure(PROJECT, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
-    assertThat(measureRepository.getRawMeasure(PROJECT, DEBT_METRIC).get().getVariations().getVariation1()).isEqualTo(-5d);
-    assertThat(measureRepository.getRawMeasure(PROJECT, FILE_COMPLEXITY_METRIC).get().getVariations().getVariation1()).isEqualTo(1d);
-    assertThat(measureRepository.getRawMeasure(PROJECT, BUILD_BREAKER_METRIC).get().getVariations().getVariation1()).isEqualTo(-1d);
-  }
-
-  private static MeasureDto newMeasureDto(int metricId, long projectId, long snapshotId, double value) {
-    return new MeasureDto().setMetricId(metricId).setComponentId(projectId).setSnapshotId(snapshotId).setValue(value);
-  }
-
-  private static Period newPeriod(int index, SnapshotDto snapshotDto) {
-    return new Period(index, "mode", null, snapshotDto.getCreatedAt(), snapshotDto.getId());
-  }
-
-  private void addRawMeasure(Component component, Metric metric, Measure measure) {
-    measureRepository.addRawMeasure(component.getReportAttributes().getRef(), metric.getKey(), measure);
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportFillMeasuresWithVariationsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportFillMeasuresWithVariationsStepTest.java
new file mode 100644 (file)
index 0000000..6b28ebf
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * 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.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+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.component.ComponentDto;
+import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.measure.MeasureDto;
+import org.sonar.db.component.ComponentTesting;
+import org.sonar.server.computation.batch.BatchReportReaderRule;
+import org.sonar.server.computation.batch.TreeRootHolderRule;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.ReportComponent;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureRepositoryRule;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricImpl;
+import org.sonar.server.computation.metric.MetricRepositoryRule;
+import org.sonar.server.computation.period.Period;
+import org.sonar.server.computation.period.PeriodsHolderRule;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.server.component.SnapshotTesting.createForComponent;
+import static org.sonar.server.component.SnapshotTesting.createForProject;
+
+@Category(DbTests.class)
+public class ReportFillMeasuresWithVariationsStepTest {
+
+  static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT);
+  static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR);
+  static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT);
+  static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL);
+
+  static final ComponentDto PROJECT_DTO = ComponentTesting.newProjectDto();
+
+  static final Component PROJECT = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).build();
+
+  @Rule
+  public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+  @Rule
+  public BatchReportReaderRule reportReader = new BatchReportReaderRule();
+
+  @Rule
+  public PeriodsHolderRule periodsHolder = new PeriodsHolderRule();
+
+  @Rule
+  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+
+  @Rule
+  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
+    .add(ISSUES_METRIC)
+    .add(DEBT_METRIC)
+    .add(FILE_COMPLEXITY_METRIC)
+    .add(BUILD_BREAKER_METRIC);
+
+  @Rule
+  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+
+  DbSession session = dbTester.getSession();
+
+  DbClient dbClient = dbTester.getDbClient();
+
+  FillMeasuresWithVariationsStep underTest;
+
+  @Before
+  public void setUp() {
+    dbTester.truncateTables();
+    dbClient.componentDao().insert(session, PROJECT_DTO);
+    session.commit();
+
+    underTest = new FillMeasuresWithVariationsStep(dbClient, treeRootHolder, periodsHolder, metricRepository, measureRepository);
+  }
+
+  @Test
+  public void do_nothing_when_no_raw_measure() {
+    SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
+    dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
+    session.commit();
+
+    periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
+
+    treeRootHolder.setRoot(PROJECT);
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasures(PROJECT).keys()).isEmpty();
+  }
+
+  @Test
+  public void do_nothing_when_no_period() {
+    Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).build();
+    treeRootHolder.setRoot(project);
+    periodsHolder.setPeriods();
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasures(project).keys()).isEmpty();
+  }
+
+  @Test
+  public void set_variation() {
+    // Project
+    SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
+    dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
+
+    // Directory
+    ComponentDto directoryDto = ComponentTesting.newDirectory(PROJECT_DTO, "dir");
+    dbClient.componentDao().insert(session, directoryDto);
+    SnapshotDto period1DirectorySnapshot = createForComponent(directoryDto, period1ProjectSnapshot);
+    dbClient.snapshotDao().insert(session, period1DirectorySnapshot);
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), directoryDto.getId(), period1DirectorySnapshot.getId(), 10d));
+    session.commit();
+
+    periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
+
+    Component directory = ReportComponent.builder(Component.Type.DIRECTORY, 2).setUuid(directoryDto.uuid()).build();
+    Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).addChildren(directory).build();
+    treeRootHolder.setRoot(project);
+
+    addRawMeasure(project, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+    addRawMeasure(directory, ISSUES_METRIC, Measure.newMeasureBuilder().create(20, null));
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasure(project, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
+    assertThat(measureRepository.getRawMeasure(directory, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(10d);
+  }
+
+  @Test
+  public void set_variations_on_all_periods() {
+    SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
+    SnapshotDto period2ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
+    SnapshotDto period3ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
+    SnapshotDto period4ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
+    SnapshotDto period5ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
+    dbClient.snapshotDao().insert(session, period1ProjectSnapshot, period2ProjectSnapshot, period3ProjectSnapshot, period4ProjectSnapshot, period5ProjectSnapshot);
+
+    dbClient.measureDao().insert(session,
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 0d),
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period2ProjectSnapshot.getId(), 20d),
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period3ProjectSnapshot.getId(), 40d),
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period4ProjectSnapshot.getId(), 80d),
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period5ProjectSnapshot.getId(), 100d));
+    session.commit();
+
+    periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot),
+      newPeriod(2, period2ProjectSnapshot),
+      newPeriod(3, period3ProjectSnapshot),
+      newPeriod(4, period4ProjectSnapshot),
+      newPeriod(5, period5ProjectSnapshot));
+
+    treeRootHolder.setRoot(PROJECT);
+
+    addRawMeasure(PROJECT, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasures(PROJECT).keys()).hasSize(1);
+
+    Measure measure = measureRepository.getRawMeasure(PROJECT, ISSUES_METRIC).get();
+    assertThat(measure.hasVariations()).isTrue();
+    assertThat(measure.getVariations().getVariation1()).isEqualTo(80d);
+    assertThat(measure.getVariations().getVariation2()).isEqualTo(60d);
+    assertThat(measure.getVariations().getVariation3()).isEqualTo(40d);
+    assertThat(measure.getVariations().getVariation4()).isEqualTo(0d);
+    assertThat(measure.getVariations().getVariation5()).isEqualTo(-20d);
+  }
+
+  @Test
+  public void set_variation_on_all_numeric_metrics() {
+    SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
+    dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
+    dbClient.measureDao().insert(session,
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d),
+      newMeasureDto(DEBT_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 10d),
+      newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 2d),
+      newMeasureDto(BUILD_BREAKER_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 1d)
+    );
+    session.commit();
+
+    periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
+
+    treeRootHolder.setRoot(PROJECT);
+
+    addRawMeasure(PROJECT, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+    addRawMeasure(PROJECT, DEBT_METRIC, Measure.newMeasureBuilder().create(5L, null));
+    addRawMeasure(PROJECT, FILE_COMPLEXITY_METRIC, Measure.newMeasureBuilder().create(3d, null));
+    addRawMeasure(PROJECT, BUILD_BREAKER_METRIC, Measure.newMeasureBuilder().create(false, null));
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasures(PROJECT).keys()).hasSize(4);
+
+    assertThat(measureRepository.getRawMeasure(PROJECT, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
+    assertThat(measureRepository.getRawMeasure(PROJECT, DEBT_METRIC).get().getVariations().getVariation1()).isEqualTo(-5d);
+    assertThat(measureRepository.getRawMeasure(PROJECT, FILE_COMPLEXITY_METRIC).get().getVariations().getVariation1()).isEqualTo(1d);
+    assertThat(measureRepository.getRawMeasure(PROJECT, BUILD_BREAKER_METRIC).get().getVariations().getVariation1()).isEqualTo(-1d);
+  }
+
+  private static MeasureDto newMeasureDto(int metricId, long projectId, long snapshotId, double value) {
+    return new MeasureDto().setMetricId(metricId).setComponentId(projectId).setSnapshotId(snapshotId).setValue(value);
+  }
+
+  private static Period newPeriod(int index, SnapshotDto snapshotDto) {
+    return new Period(index, "mode", null, snapshotDto.getCreatedAt(), snapshotDto.getId());
+  }
+
+  private void addRawMeasure(Component component, Metric metric, Measure measure) {
+    measureRepository.addRawMeasure(component.getReportAttributes().getRef(), metric.getKey(), measure);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsFillMeasuresWithVariationsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsFillMeasuresWithVariationsStepTest.java
new file mode 100644 (file)
index 0000000..e1b2195
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * 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.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+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.component.ComponentDto;
+import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.measure.MeasureDto;
+import org.sonar.server.computation.batch.BatchReportReaderRule;
+import org.sonar.server.computation.batch.TreeRootHolderRule;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.ViewsComponent;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureRepositoryRule;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricImpl;
+import org.sonar.server.computation.metric.MetricRepositoryRule;
+import org.sonar.server.computation.period.Period;
+import org.sonar.server.computation.period.PeriodsHolderRule;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.server.component.SnapshotTesting.createForComponent;
+import static org.sonar.server.component.SnapshotTesting.createForProject;
+import static org.sonar.server.component.SnapshotTesting.createForView;
+
+@Category(DbTests.class)
+public class ViewsFillMeasuresWithVariationsStepTest {
+
+  static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT);
+  static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR);
+  static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT);
+  static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL);
+
+  static final ComponentDto VIEW_DTO = ComponentTesting.newView();
+
+  static final Component VIEW = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).build();
+
+  @Rule
+  public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+  @Rule
+  public BatchReportReaderRule reportReader = new BatchReportReaderRule();
+
+  @Rule
+  public PeriodsHolderRule periodsHolder = new PeriodsHolderRule();
+
+  @Rule
+  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+
+  @Rule
+  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
+    .add(ISSUES_METRIC)
+    .add(DEBT_METRIC)
+    .add(FILE_COMPLEXITY_METRIC)
+    .add(BUILD_BREAKER_METRIC);
+
+  @Rule
+  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+
+  DbSession session = dbTester.getSession();
+
+  DbClient dbClient = dbTester.getDbClient();
+
+  FillMeasuresWithVariationsStep underTest;
+
+  @Before
+  public void setUp() {
+    dbTester.truncateTables();
+    dbClient.componentDao().insert(session, VIEW_DTO);
+    session.commit();
+
+    underTest = new FillMeasuresWithVariationsStep(dbClient, treeRootHolder, periodsHolder, metricRepository, measureRepository);
+  }
+
+  @Test
+  public void do_nothing_when_no_raw_measure() {
+    SnapshotDto period1ViewSnapshot = createForView(VIEW_DTO);
+    dbClient.snapshotDao().insert(session, period1ViewSnapshot);
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d));
+    session.commit();
+
+    periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
+
+    treeRootHolder.setRoot(VIEW);
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasures(VIEW).keys()).isEmpty();
+  }
+
+  @Test
+  public void do_nothing_when_no_period() {
+    Component view = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).build();
+    treeRootHolder.setRoot(view);
+    periodsHolder.setPeriods();
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasures(view).keys()).isEmpty();
+  }
+
+  @Test
+  public void set_variation() {
+    // View
+    SnapshotDto period1ViewSnapshot = createForView(VIEW_DTO);
+    dbClient.snapshotDao().insert(session, period1ViewSnapshot);
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d));
+
+    // SubView
+    ComponentDto subviewDto = ComponentTesting.newSubView(VIEW_DTO, "dir", "who cares?");
+    dbClient.componentDao().insert(session, subviewDto);
+    SnapshotDto period1SubviewSnapshot = createForComponent(subviewDto, period1ViewSnapshot);
+    dbClient.snapshotDao().insert(session, period1SubviewSnapshot);
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), subviewDto.getId(), period1SubviewSnapshot.getId(), 10d));
+    session.commit();
+
+    periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
+
+    Component subview = ViewsComponent.builder(Component.Type.SUBVIEW, 2).setUuid(subviewDto.uuid()).build();
+    Component view = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).addChildren(subview).build();
+    treeRootHolder.setRoot(view);
+
+    addRawMeasure(view, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+    addRawMeasure(subview, ISSUES_METRIC, Measure.newMeasureBuilder().create(20, null));
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasure(view, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
+    assertThat(measureRepository.getRawMeasure(subview, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(10d);
+  }
+
+  @Test
+  public void set_variations_on_all_periods() {
+    SnapshotDto period1ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
+    SnapshotDto period2ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
+    SnapshotDto period3ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
+    SnapshotDto period4ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
+    SnapshotDto period5ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
+    dbClient.snapshotDao().insert(session, period1ViewSnapshot, period2ViewSnapshot, period3ViewSnapshot, period4ViewSnapshot, period5ViewSnapshot);
+
+    dbClient.measureDao().insert(session,
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 0d),
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period2ViewSnapshot.getId(), 20d),
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period3ViewSnapshot.getId(), 40d),
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period4ViewSnapshot.getId(), 80d),
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period5ViewSnapshot.getId(), 100d));
+    session.commit();
+
+    periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot),
+      newPeriod(2, period2ViewSnapshot),
+      newPeriod(3, period3ViewSnapshot),
+      newPeriod(4, period4ViewSnapshot),
+      newPeriod(5, period5ViewSnapshot));
+
+    treeRootHolder.setRoot(VIEW);
+
+    addRawMeasure(VIEW, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasures(VIEW).keys()).hasSize(1);
+
+    Measure measure = measureRepository.getRawMeasure(VIEW, ISSUES_METRIC).get();
+    assertThat(measure.hasVariations()).isTrue();
+    assertThat(measure.getVariations().getVariation1()).isEqualTo(80d);
+    assertThat(measure.getVariations().getVariation2()).isEqualTo(60d);
+    assertThat(measure.getVariations().getVariation3()).isEqualTo(40d);
+    assertThat(measure.getVariations().getVariation4()).isEqualTo(0d);
+    assertThat(measure.getVariations().getVariation5()).isEqualTo(-20d);
+  }
+
+  @Test
+  public void set_variation_on_all_numeric_metrics() {
+    SnapshotDto period1ViewSnapshot = createForProject(VIEW_DTO);
+    dbClient.snapshotDao().insert(session, period1ViewSnapshot);
+    dbClient.measureDao().insert(session,
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d),
+      newMeasureDto(DEBT_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 10d),
+      newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 2d),
+      newMeasureDto(BUILD_BREAKER_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 1d)
+    );
+    session.commit();
+
+    periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
+
+    treeRootHolder.setRoot(VIEW);
+
+    addRawMeasure(VIEW, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+    addRawMeasure(VIEW, DEBT_METRIC, Measure.newMeasureBuilder().create(5L, null));
+    addRawMeasure(VIEW, FILE_COMPLEXITY_METRIC, Measure.newMeasureBuilder().create(3d, null));
+    addRawMeasure(VIEW, BUILD_BREAKER_METRIC, Measure.newMeasureBuilder().create(false, null));
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasures(VIEW).keys()).hasSize(4);
+
+    assertThat(measureRepository.getRawMeasure(VIEW, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
+    assertThat(measureRepository.getRawMeasure(VIEW, DEBT_METRIC).get().getVariations().getVariation1()).isEqualTo(-5d);
+    assertThat(measureRepository.getRawMeasure(VIEW, FILE_COMPLEXITY_METRIC).get().getVariations().getVariation1()).isEqualTo(1d);
+    assertThat(measureRepository.getRawMeasure(VIEW, BUILD_BREAKER_METRIC).get().getVariations().getVariation1()).isEqualTo(-1d);
+  }
+
+  private static MeasureDto newMeasureDto(int metricId, long projectId, long snapshotId, double value) {
+    return new MeasureDto().setMetricId(metricId).setComponentId(projectId).setSnapshotId(snapshotId).setValue(value);
+  }
+
+  private static Period newPeriod(int index, SnapshotDto snapshotDto) {
+    return new Period(index, "mode", null, snapshotDto.getCreatedAt(), snapshotDto.getId());
+  }
+
+  private void addRawMeasure(Component component, Metric metric, Measure measure) {
+    measureRepository.add(component, metric, measure);
+  }
+}