]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8418 Stop computing ratings for views 1407/head
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Tue, 22 Nov 2016 12:36:51 +0000 (13:36 +0100)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Thu, 24 Nov 2016 10:11:59 +0000 (11:11 +0100)
Ratings for views should be computed in Governance

server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitor.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/ReliabilityAndSecurityRatingMeasuresVisitor.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitorForReportTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitorForViewsTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitorTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/ReliabilityAndSecurityRatingMeasuresVisitorForReportTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/ReliabilityAndSecurityRatingMeasuresVisitorForViewsTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/ReliabilityAndSecurityRatingMeasuresVisitorTest.java [new file with mode: 0644]

index 8859f8894500584c7d56e4fc0a97c0c00373d9c9..80a340eb1d327ce0eaafdfc981726176c1bf2215 100644 (file)
@@ -21,8 +21,6 @@ package org.sonar.server.computation.task.projectanalysis.qualitymodel;
 
 import com.google.common.base.Optional;
 import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
 import org.sonar.server.computation.task.projectanalysis.component.Component;
 import org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit;
 import org.sonar.server.computation.task.projectanalysis.component.PathAwareVisitorAdapter;
@@ -43,15 +41,13 @@ import static org.sonar.server.computation.task.projectanalysis.component.Compon
 import static org.sonar.server.computation.task.projectanalysis.measure.Measure.newMeasureBuilder;
 
 /**
- * Compute measures related to maintainability :
+ * Compute measures related to maintainability for projects and descendants :
  * {@link CoreMetrics#DEVELOPMENT_COST_KEY}
  * {@link CoreMetrics#SQALE_DEBT_RATIO_KEY}
  * {@link CoreMetrics#SQALE_RATING_KEY}
  * {@link CoreMetrics#EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY}
  */
 public class MaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<MaintainabilityMeasuresVisitor.Counter> {
-  private static final Logger LOG = Loggers.get(MaintainabilityMeasuresVisitor.class);
-
   private final MeasureRepository measureRepository;
   private final RatingSettings ratingSettings;
   private final RatingGrid ratingGrid;
@@ -65,7 +61,7 @@ public class MaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<Main
   private final Metric effortToMaintainabilityRatingAMetric;
 
   public MaintainabilityMeasuresVisitor(MetricRepository metricRepository, MeasureRepository measureRepository, RatingSettings ratingSettings) {
-    super(CrawlerDepthLimit.LEAVES, POST_ORDER, CounterFactory.INSTANCE);
+    super(CrawlerDepthLimit.FILE, POST_ORDER, CounterFactory.INSTANCE);
     this.measureRepository = measureRepository;
     this.ratingSettings = ratingSettings;
     this.ratingGrid = ratingSettings.getRatingGrid();
@@ -108,28 +104,6 @@ public class MaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<Main
     return ncloc * ratingSettings.getDevCost(file.getFileAttributes().getLanguageKey());
   }
 
-  @Override
-  public void visitView(Component view, Path<Counter> path) {
-    computeAndSaveMeasures(view, path);
-  }
-
-  @Override
-  public void visitSubView(Component subView, Path<Counter> path) {
-    computeAndSaveMeasures(subView, path);
-  }
-
-  @Override
-  public void visitProjectView(Component projectView, Path<Counter> path) {
-    Optional<Measure> developmentCostMeasure = measureRepository.getRawMeasure(projectView, developmentCostMetric);
-    if (developmentCostMeasure.isPresent()) {
-      try {
-        path.parent().addDevCosts(Long.valueOf(developmentCostMeasure.get().getStringValue()));
-      } catch (NumberFormatException e) {
-        LOG.trace("Failed to parse value of metric {} for component {}", developmentCostMetric.getName(), projectView.getKey());
-      }
-    }
-  }
-
   private void computeAndSaveMeasures(Component component, Path<Counter> path) {
     addDevelopmentCostMeasure(component, path.current());
 
@@ -210,11 +184,5 @@ public class MaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<Main
     public Counter createForAny(Component component) {
       return new Counter();
     }
-
-    /** Counter is not used at ProjectView level, saves on instantiating useless objects */
-    @Override
-    public Counter createForProjectView(Component projectView) {
-      return null;
-    }
   }
 }
index 43057b08f93ae286c1fe9370a7e0a32241f89e2f..6fd0994cb071b4ff9d0948c825bc74c54498fca0 100644 (file)
@@ -20,7 +20,6 @@
 
 package org.sonar.server.computation.task.projectanalysis.qualitymodel;
 
-import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableMap;
 import java.util.Map;
 import org.sonar.api.ce.measure.Issue;
@@ -44,7 +43,7 @@ import static org.sonar.api.rule.Severity.MINOR;
 import static org.sonar.api.rules.RuleType.BUG;
 import static org.sonar.api.rules.RuleType.VULNERABILITY;
 import static org.sonar.server.computation.task.projectanalysis.component.ComponentVisitor.Order.POST_ORDER;
-import static org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit.LEAVES;
+import static org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit.FILE;
 import static org.sonar.server.computation.task.projectanalysis.measure.Measure.newMeasureBuilder;
 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating;
 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.A;
@@ -52,10 +51,9 @@ import static org.sonar.server.computation.task.projectanalysis.qualitymodel.Rat
 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.C;
 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.D;
 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.E;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.valueOf;
 
 /**
- * Compute following measures :
+ * Compute following measures for projects and descendants:
  * {@link CoreMetrics#RELIABILITY_RATING_KEY}
  * {@link CoreMetrics#SECURITY_RATING_KEY}
  */
@@ -78,7 +76,7 @@ public class ReliabilityAndSecurityRatingMeasuresVisitor extends PathAwareVisito
   private final Map<String, Metric> metricsByKey;
 
   public ReliabilityAndSecurityRatingMeasuresVisitor(MetricRepository metricRepository, MeasureRepository measureRepository, ComponentIssuesRepository componentIssuesRepository) {
-    super(LEAVES, POST_ORDER, CounterFactory.INSTANCE);
+    super(FILE, POST_ORDER, CounterFactory.INSTANCE);
     this.measureRepository = measureRepository;
     this.componentIssuesRepository = componentIssuesRepository;
 
@@ -111,26 +109,6 @@ public class ReliabilityAndSecurityRatingMeasuresVisitor extends PathAwareVisito
     computeAndSaveMeasures(file, path);
   }
 
-  @Override
-  public void visitView(Component view, Path<Counter> path) {
-    computeAndSaveMeasures(view, path);
-  }
-
-  @Override
-  public void visitSubView(Component subView, Path<Counter> path) {
-    computeAndSaveMeasures(subView, path);
-  }
-
-  @Override
-  public void visitProjectView(Component projectView, Path<Counter> path) {
-    path.parent().ratingValueByMetric.entrySet().forEach(entry -> {
-      Optional<Measure> ratingMeasure = measureRepository.getRawMeasure(projectView, metricsByKey.get(entry.getKey()));
-      if (ratingMeasure.isPresent()) {
-        entry.getValue().increment(valueOf(ratingMeasure.get().getData()));
-      }
-    });
-  }
-
   private void computeAndSaveMeasures(Component component, Path<Counter> path) {
     processIssues(component, path);
     path.current().ratingValueByMetric.entrySet().forEach(
@@ -190,13 +168,5 @@ public class ReliabilityAndSecurityRatingMeasuresVisitor extends PathAwareVisito
     public Counter createForAny(Component component) {
       return new Counter();
     }
-
-    /**
-     * Counter is not used at ProjectView level, saves on instantiating useless objects
-     */
-    @Override
-    public Counter createForProjectView(Component projectView) {
-      return null;
-    }
   }
 }
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitorForReportTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitorForReportTest.java
deleted file mode 100644 (file)
index 4dd1347..0000000
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.task.projectanalysis.qualitymodel;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.server.computation.task.projectanalysis.component.Component;
-import org.sonar.server.computation.task.projectanalysis.component.FileAttributes;
-import org.sonar.server.computation.task.projectanalysis.component.ReportComponent;
-import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
-import org.sonar.server.computation.task.projectanalysis.component.VisitorsCrawler;
-import org.sonar.server.computation.task.projectanalysis.issue.ComponentIssuesRepositoryRule;
-import org.sonar.server.computation.task.projectanalysis.measure.Measure;
-import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepositoryRule;
-import org.sonar.server.computation.task.projectanalysis.metric.MetricRepositoryRule;
-import org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating;
-
-import static java.util.Collections.singletonList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.api.measures.CoreMetrics.DEVELOPMENT_COST;
-import static org.sonar.api.measures.CoreMetrics.DEVELOPMENT_COST_KEY;
-import static org.sonar.api.measures.CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A;
-import static org.sonar.api.measures.CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY;
-import static org.sonar.api.measures.CoreMetrics.NCLOC;
-import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY;
-import static org.sonar.api.measures.CoreMetrics.SQALE_DEBT_RATIO;
-import static org.sonar.api.measures.CoreMetrics.SQALE_DEBT_RATIO_KEY;
-import static org.sonar.api.measures.CoreMetrics.SQALE_RATING;
-import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY;
-import static org.sonar.api.measures.CoreMetrics.TECHNICAL_DEBT;
-import static org.sonar.api.measures.CoreMetrics.TECHNICAL_DEBT_KEY;
-import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.DIRECTORY;
-import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.FILE;
-import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.MODULE;
-import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT;
-import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
-import static org.sonar.server.computation.task.projectanalysis.measure.Measure.newMeasureBuilder;
-import static org.sonar.server.computation.task.projectanalysis.measure.MeasureRepoEntry.entryOf;
-import static org.sonar.server.computation.task.projectanalysis.measure.MeasureRepoEntry.toEntries;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.A;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.C;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.E;
-
-public class MaintainabilityMeasuresVisitorForReportTest {
-
-  static final String LANGUAGE_KEY_1 = "lKey1";
-  static final String LANGUAGE_KEY_2 = "lKey2";
-
-  static final double[] RATING_GRID = new double[] {0.1, 0.2, 0.5, 1};
-
-  static final long DEV_COST_LANGUAGE_1 = 30;
-  static final long DEV_COST_LANGUAGE_2 = 42;
-
-  static final int PROJECT_REF = 1;
-  static final int MODULE_REF = 12;
-  static final int DIRECTORY_REF = 123;
-  static final int FILE_1_REF = 1231;
-  static final int FILE_2_REF = 1232;
-
-  static final Component ROOT_PROJECT = builder(Component.Type.PROJECT, PROJECT_REF).setKey("project")
-    .addChildren(
-      builder(MODULE, MODULE_REF).setKey("module")
-        .addChildren(
-          builder(DIRECTORY, DIRECTORY_REF).setKey("directory")
-            .addChildren(
-              builder(FILE, FILE_1_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_KEY_1)).setKey("file1").build(),
-              builder(FILE, FILE_2_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_KEY_1)).setKey("file2").build())
-            .build())
-        .build())
-    .build();
-
-  @Rule
-  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
-
-  @Rule
-  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
-    .add(NCLOC)
-    .add(DEVELOPMENT_COST)
-    .add(TECHNICAL_DEBT)
-    .add(SQALE_DEBT_RATIO)
-    .add(SQALE_RATING)
-    .add(EFFORT_TO_REACH_MAINTAINABILITY_RATING_A);
-
-  @Rule
-  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
-
-  @Rule
-  public ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
-
-  private RatingSettings ratingSettings = mock(RatingSettings.class);
-
-  private VisitorsCrawler underTest;
-
-  @Before
-  public void setUp() {
-    // assumes rating configuration is consistent
-    when(ratingSettings.getRatingGrid()).thenReturn(new RatingGrid(RATING_GRID));
-    when(ratingSettings.getDevCost(LANGUAGE_KEY_1)).thenReturn(DEV_COST_LANGUAGE_1);
-    when(ratingSettings.getDevCost(LANGUAGE_KEY_2)).thenReturn(DEV_COST_LANGUAGE_2);
-
-    underTest = new VisitorsCrawler(singletonList(new MaintainabilityMeasuresVisitor(metricRepository, measureRepository, ratingSettings)));
-  }
-
-  @Test
-  public void measures_created_for_project_are_all_zero_when_they_have_no_FILE_child() {
-    ReportComponent root = builder(PROJECT, 1).build();
-    treeRootHolder.setRoot(root);
-
-    underTest.visit(root);
-
-    assertThat(toEntries(measureRepository.getRawMeasures(root)))
-      .containsOnly(
-        entryOf(DEVELOPMENT_COST_KEY, newMeasureBuilder().create("0")),
-        entryOf(SQALE_DEBT_RATIO_KEY, newMeasureBuilder().create(0d, 1)),
-        entryOf(SQALE_RATING_KEY, createMaintainabilityRatingMeasure(A)),
-        entryOf(EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY, newMeasureBuilder().create(0L)));
-  }
-
-  @Test
-  public void compute_development_cost() {
-    ReportComponent root = builder(PROJECT, 1)
-      .addChildren(
-        builder(MODULE, 11)
-          .addChildren(
-            builder(DIRECTORY, 111)
-              .addChildren(
-                createFileComponent(LANGUAGE_KEY_1, 1111),
-                createFileComponent(LANGUAGE_KEY_2, 1112),
-                // Unit test should not be ignored
-                builder(FILE, 1113).setFileAttributes(new FileAttributes(true, LANGUAGE_KEY_1)).build())
-              .build(),
-            builder(DIRECTORY, 112)
-              .addChildren(
-                createFileComponent(LANGUAGE_KEY_2, 1121))
-              .build())
-          .build(),
-        builder(MODULE, 12)
-          .addChildren(
-            builder(DIRECTORY, 121)
-              .addChildren(
-                createFileComponent(LANGUAGE_KEY_1, 1211))
-              .build(),
-            builder(DIRECTORY, 122).build())
-          .build(),
-        builder(MODULE, 13).build())
-      .build();
-
-    treeRootHolder.setRoot(root);
-
-    int ncloc1111 = 10;
-    addRawMeasure(NCLOC_KEY, 1111, ncloc1111);
-
-    int ncloc1112 = 12;
-    addRawMeasure(NCLOC_KEY, 1112, ncloc1112);
-
-    int ncloc1113 = 15;
-    addRawMeasure(NCLOC_KEY, 1113, ncloc1113);
-
-    int nclocValue1121 = 30;
-    addRawMeasure(NCLOC_KEY, 1121, nclocValue1121);
-
-    int ncloc1211 = 20;
-    addRawMeasure(NCLOC_KEY, 1211, ncloc1211);
-
-    underTest.visit(root);
-
-    // verify measures on files
-    verifyAddedRawMeasure(1111, DEVELOPMENT_COST_KEY, Long.toString(ncloc1111 * DEV_COST_LANGUAGE_1));
-    verifyAddedRawMeasure(1112, DEVELOPMENT_COST_KEY, Long.toString(ncloc1112 * DEV_COST_LANGUAGE_2));
-    verifyAddedRawMeasure(1113, DEVELOPMENT_COST_KEY, Long.toString(ncloc1113 * DEV_COST_LANGUAGE_1));
-    verifyAddedRawMeasure(1121, DEVELOPMENT_COST_KEY, Long.toString(nclocValue1121 * DEV_COST_LANGUAGE_2));
-    verifyAddedRawMeasure(1211, DEVELOPMENT_COST_KEY, Long.toString(ncloc1211 * DEV_COST_LANGUAGE_1));
-
-    // directory has no children => no file => 0 everywhere and A rating
-    verifyAddedRawMeasure(122, DEVELOPMENT_COST_KEY, "0");
-
-    // directory has children => dev cost is aggregated
-    verifyAddedRawMeasure(111, DEVELOPMENT_COST_KEY, Long.toString(
-      ncloc1111 * DEV_COST_LANGUAGE_1 +
-        ncloc1112 * DEV_COST_LANGUAGE_2 +
-        ncloc1113 * DEV_COST_LANGUAGE_1));
-    verifyAddedRawMeasure(112, DEVELOPMENT_COST_KEY, Long.toString(nclocValue1121 * DEV_COST_LANGUAGE_2));
-    verifyAddedRawMeasure(121, DEVELOPMENT_COST_KEY, Long.toString(ncloc1211 * DEV_COST_LANGUAGE_1));
-
-    // just for fun, we didn't define any debt on module => they must all have rating A
-    verifyAddedRawMeasure(11, DEVELOPMENT_COST_KEY, Long.toString(
-      ncloc1111 * DEV_COST_LANGUAGE_1 +
-        ncloc1112 * DEV_COST_LANGUAGE_2 +
-        ncloc1113 * DEV_COST_LANGUAGE_1 +
-        nclocValue1121 * DEV_COST_LANGUAGE_2));
-    verifyAddedRawMeasure(12, DEVELOPMENT_COST_KEY, Long.toString(ncloc1211 * DEV_COST_LANGUAGE_1));
-    verifyAddedRawMeasure(13, DEVELOPMENT_COST_KEY, "0");
-    verifyAddedRawMeasure(1, DEVELOPMENT_COST_KEY, Long.toString(
-      ncloc1111 * DEV_COST_LANGUAGE_1 +
-        ncloc1112 * DEV_COST_LANGUAGE_2 +
-        ncloc1113 * DEV_COST_LANGUAGE_1 +
-        nclocValue1121 * DEV_COST_LANGUAGE_2 +
-        ncloc1211 * DEV_COST_LANGUAGE_1));
-  }
-
-  @Test
-  public void compute_maintainability_debt_ratio_measure() throws Exception {
-    treeRootHolder.setRoot(ROOT_PROJECT);
-
-    int file1Ncloc = 10;
-    addRawMeasure(NCLOC_KEY, FILE_1_REF, file1Ncloc);
-    long file1MaintainabilityCost = 100L;
-    addRawMeasure(TECHNICAL_DEBT_KEY, FILE_1_REF, file1MaintainabilityCost);
-
-    int file2Ncloc = 5;
-    addRawMeasure(NCLOC_KEY, FILE_2_REF, file2Ncloc);
-    long file2MaintainabilityCost = 1L;
-    addRawMeasure(TECHNICAL_DEBT_KEY, FILE_2_REF, file2MaintainabilityCost);
-
-    long directoryMaintainabilityCost = 100L;
-    addRawMeasure(TECHNICAL_DEBT_KEY, DIRECTORY_REF, directoryMaintainabilityCost);
-
-    long moduleMaintainabilityCost = 100L;
-    addRawMeasure(TECHNICAL_DEBT_KEY, MODULE_REF, moduleMaintainabilityCost);
-
-    long projectMaintainabilityCost = 1000L;
-    addRawMeasure(TECHNICAL_DEBT_KEY, PROJECT_REF, projectMaintainabilityCost);
-
-    underTest.visit(ROOT_PROJECT);
-
-    verifyAddedRawMeasure(FILE_1_REF, SQALE_DEBT_RATIO_KEY, file1MaintainabilityCost * 1d / (file1Ncloc * DEV_COST_LANGUAGE_1) * 100);
-    verifyAddedRawMeasure(FILE_2_REF, SQALE_DEBT_RATIO_KEY, file2MaintainabilityCost * 1d / (file2Ncloc * DEV_COST_LANGUAGE_1) * 100);
-    verifyAddedRawMeasure(DIRECTORY_REF, SQALE_DEBT_RATIO_KEY, directoryMaintainabilityCost * 1d / ((file1Ncloc + file2Ncloc) * DEV_COST_LANGUAGE_1) * 100);
-    verifyAddedRawMeasure(MODULE_REF, SQALE_DEBT_RATIO_KEY, moduleMaintainabilityCost * 1d / ((file1Ncloc + file2Ncloc) * DEV_COST_LANGUAGE_1) * 100);
-    verifyAddedRawMeasure(PROJECT_REF, SQALE_DEBT_RATIO_KEY, projectMaintainabilityCost * 1d / ((file1Ncloc + file2Ncloc) * DEV_COST_LANGUAGE_1) * 100);
-  }
-
-  @Test
-  public void compute_maintainability_rating_measure() throws Exception {
-    treeRootHolder.setRoot(ROOT_PROJECT);
-
-    addRawMeasure(NCLOC_KEY, FILE_1_REF, 10);
-    addRawMeasure(TECHNICAL_DEBT_KEY, FILE_1_REF, 100L);
-
-    addRawMeasure(NCLOC_KEY, FILE_2_REF, 5);
-    addRawMeasure(TECHNICAL_DEBT_KEY, FILE_2_REF, 1L);
-
-    addRawMeasure(TECHNICAL_DEBT_KEY, DIRECTORY_REF, 100L);
-    addRawMeasure(TECHNICAL_DEBT_KEY, MODULE_REF, 100L);
-    addRawMeasure(TECHNICAL_DEBT_KEY, PROJECT_REF, 1000L);
-
-    underTest.visit(ROOT_PROJECT);
-
-    verifyAddedRawMeasure(FILE_1_REF, SQALE_RATING_KEY, C);
-    verifyAddedRawMeasure(FILE_2_REF, SQALE_RATING_KEY, A);
-    verifyAddedRawMeasure(DIRECTORY_REF, SQALE_RATING_KEY, C);
-    verifyAddedRawMeasure(MODULE_REF, SQALE_RATING_KEY, C);
-    verifyAddedRawMeasure(PROJECT_REF, SQALE_RATING_KEY, E);
-  }
-
-  @Test
-  public void compute_effort_to_maintainability_rating_A_measure() throws Exception {
-    treeRootHolder.setRoot(ROOT_PROJECT);
-
-    int file1Ncloc = 10;
-    long file1Effort = 100L;
-    addRawMeasure(NCLOC_KEY, FILE_1_REF, file1Ncloc);
-    addRawMeasure(TECHNICAL_DEBT_KEY, FILE_1_REF, file1Effort);
-
-    int file2Ncloc = 5;
-    long file2Effort = 20L;
-    addRawMeasure(NCLOC_KEY, FILE_2_REF, file2Ncloc);
-    addRawMeasure(TECHNICAL_DEBT_KEY, FILE_2_REF, file2Effort);
-
-    long dirEffort = 120L;
-    addRawMeasure(TECHNICAL_DEBT_KEY, DIRECTORY_REF, dirEffort);
-
-    long moduleEffort = 120L;
-    addRawMeasure(TECHNICAL_DEBT_KEY, MODULE_REF, moduleEffort);
-
-    long projectEffort = 150L;
-    addRawMeasure(TECHNICAL_DEBT_KEY, PROJECT_REF, projectEffort);
-
-    underTest.visit(ROOT_PROJECT);
-
-    verifyAddedRawMeasure(FILE_1_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
-      (long) (file1Effort - RATING_GRID[0] * file1Ncloc * DEV_COST_LANGUAGE_1));
-    verifyAddedRawMeasure(FILE_2_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
-      (long) (file2Effort - RATING_GRID[0] * file2Ncloc * DEV_COST_LANGUAGE_1));
-    verifyAddedRawMeasure(DIRECTORY_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
-      (long) (dirEffort - RATING_GRID[0] * (file1Ncloc + file2Ncloc) * DEV_COST_LANGUAGE_1));
-    verifyAddedRawMeasure(MODULE_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
-      (long) (moduleEffort - RATING_GRID[0] * (file1Ncloc + file2Ncloc) * DEV_COST_LANGUAGE_1));
-    verifyAddedRawMeasure(PROJECT_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
-      (long) (projectEffort - RATING_GRID[0] * (file1Ncloc + file2Ncloc) * DEV_COST_LANGUAGE_1));
-  }
-
-  @Test
-  public void compute_0_effort_to_maintainability_rating_A_when_effort_is_lower_than_dev_cost() throws Exception {
-    treeRootHolder.setRoot(ROOT_PROJECT);
-
-    addRawMeasure(NCLOC_KEY, FILE_1_REF, 10);
-    addRawMeasure(TECHNICAL_DEBT_KEY, FILE_1_REF, 2L);
-
-    underTest.visit(ROOT_PROJECT);
-
-    verifyAddedRawMeasure(FILE_1_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY, 0L);
-  }
-
-  @Test
-  public void effort_to_maintainability_rating_A_is_same_as_effort_when_no_dev_cost() throws Exception {
-    treeRootHolder.setRoot(ROOT_PROJECT);
-
-    addRawMeasure(TECHNICAL_DEBT_KEY, FILE_1_REF, 100L);
-
-    underTest.visit(ROOT_PROJECT);
-
-    verifyAddedRawMeasure(FILE_1_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY, 100);
-  }
-
-  private void addRawMeasure(String metricKey, int componentRef, long value) {
-    measureRepository.addRawMeasure(componentRef, metricKey, newMeasureBuilder().create(value));
-  }
-
-  private void addRawMeasure(String metricKey, int componentRef, int value) {
-    measureRepository.addRawMeasure(componentRef, metricKey, newMeasureBuilder().create(value));
-  }
-
-  private void verifyAddedRawMeasure(int componentRef, String metricKey, long value) {
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(entryOf(metricKey, newMeasureBuilder().create(value)));
-  }
-
-  private void verifyAddedRawMeasure(int componentRef, String metricKey, double value) {
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(entryOf(metricKey, newMeasureBuilder().create(value, 1)));
-  }
-
-  private void verifyAddedRawMeasure(int componentRef, String metricKey, Rating rating) {
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(entryOf(metricKey, newMeasureBuilder().create(rating.getIndex(), rating.name())));
-  }
-
-  private void verifyAddedRawMeasure(int componentRef, String metricKey, String value) {
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(entryOf(metricKey, newMeasureBuilder().create(value)));
-  }
-
-  private static ReportComponent createFileComponent(String languageKey1, int fileRef) {
-    return builder(FILE, fileRef).setFileAttributes(new FileAttributes(false, languageKey1)).build();
-  }
-
-  private static Measure createMaintainabilityRatingMeasure(Rating rating) {
-    return newMeasureBuilder().create(rating.getIndex(), rating.name());
-  }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitorForViewsTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitorForViewsTest.java
deleted file mode 100644 (file)
index bbc984e..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.task.projectanalysis.qualitymodel;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
-import org.sonar.server.computation.task.projectanalysis.component.ViewsComponent;
-import org.sonar.server.computation.task.projectanalysis.component.VisitorsCrawler;
-import org.sonar.server.computation.task.projectanalysis.measure.Measure;
-import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepositoryRule;
-import org.sonar.server.computation.task.projectanalysis.metric.MetricRepositoryRule;
-import org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating;
-
-import static java.util.Collections.singletonList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.api.measures.CoreMetrics.DEVELOPMENT_COST;
-import static org.sonar.api.measures.CoreMetrics.DEVELOPMENT_COST_KEY;
-import static org.sonar.api.measures.CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A;
-import static org.sonar.api.measures.CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY;
-import static org.sonar.api.measures.CoreMetrics.NCLOC;
-import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING;
-import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING;
-import static org.sonar.api.measures.CoreMetrics.SQALE_DEBT_RATIO;
-import static org.sonar.api.measures.CoreMetrics.SQALE_DEBT_RATIO_KEY;
-import static org.sonar.api.measures.CoreMetrics.SQALE_RATING;
-import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY;
-import static org.sonar.api.measures.CoreMetrics.TECHNICAL_DEBT;
-import static org.sonar.api.measures.CoreMetrics.TECHNICAL_DEBT_KEY;
-import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT_VIEW;
-import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.SUBVIEW;
-import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.VIEW;
-import static org.sonar.server.computation.task.projectanalysis.component.ViewsComponent.builder;
-import static org.sonar.server.computation.task.projectanalysis.measure.Measure.newMeasureBuilder;
-import static org.sonar.server.computation.task.projectanalysis.measure.MeasureRepoEntry.entryOf;
-import static org.sonar.server.computation.task.projectanalysis.measure.MeasureRepoEntry.toEntries;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.A;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.B;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.D;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.E;
-
-public class MaintainabilityMeasuresVisitorForViewsTest {
-
-  private static final double[] RATING_GRID = new double[] {34, 50, 362, 900, 36258};
-
-  private static final int ROOT_REF = 1;
-  private static final int SUBVIEW_REF = 11;
-  private static final int SUB_SUBVIEW_1_REF = 111;
-  private static final int SUB_SUBVIEW_2_REF = 112;
-  private static final int PROJECT_VIEW_1_REF = 1111;
-  private static final int PROJECT_VIEW_2_REF = 1112;
-  private static final int PROJECT_VIEW_3_REF = 1121;
-  private static final int PROJECT_VIEW_4_REF = 12;
-
-  @Rule
-  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule()
-    .setRoot(builder(VIEW, ROOT_REF)
-      .addChildren(
-        builder(SUBVIEW, SUBVIEW_REF)
-          .addChildren(
-            builder(SUBVIEW, SUB_SUBVIEW_1_REF)
-              .addChildren(
-                builder(PROJECT_VIEW, PROJECT_VIEW_1_REF).build(),
-                builder(PROJECT_VIEW, PROJECT_VIEW_2_REF).build())
-              .build(),
-            builder(SUBVIEW, SUB_SUBVIEW_2_REF)
-              .addChildren(
-                builder(PROJECT_VIEW, PROJECT_VIEW_3_REF).build())
-              .build())
-          .build(),
-        builder(PROJECT_VIEW, PROJECT_VIEW_4_REF).build())
-      .build());
-
-  @Rule
-  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
-    .add(NCLOC)
-    .add(DEVELOPMENT_COST)
-    .add(TECHNICAL_DEBT)
-    .add(SQALE_DEBT_RATIO)
-    .add(SQALE_RATING)
-    .add(EFFORT_TO_REACH_MAINTAINABILITY_RATING_A)
-    .add(RELIABILITY_RATING)
-    .add(SECURITY_RATING);
-
-  @Rule
-  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
-
-  private RatingSettings ratingSettings = mock(RatingSettings.class);
-
-  private VisitorsCrawler underTest;
-
-  @Before
-  public void setUp() {
-    when(ratingSettings.getRatingGrid()).thenReturn(new RatingGrid(RATING_GRID));
-    underTest = new VisitorsCrawler(singletonList(new MaintainabilityMeasuresVisitor(metricRepository, measureRepository, ratingSettings)));
-  }
-
-  @Test
-  public void measures_created_for_view_are_all_zero_when_no_child() {
-    ViewsComponent root = builder(VIEW, 1).build();
-    treeRootHolder.setRoot(root);
-
-    underTest.visit(root);
-
-    assertThat(toEntries(measureRepository.getRawMeasures(root)))
-      .containsOnly(
-        entryOf(DEVELOPMENT_COST_KEY, newMeasureBuilder().create("0")),
-        entryOf(SQALE_DEBT_RATIO_KEY, newMeasureBuilder().create(0d, 1)),
-        entryOf(SQALE_RATING_KEY, createMaintainabilityRatingMeasure(A)),
-        entryOf(EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY, newMeasureBuilder().create(0L)));
-  }
-
-  @Test
-  public void verify_aggregation_of_developmentCost_and_value_of_measures_computed_from_that() {
-    long debtRoot = 9999l;
-    long debtSubView = 96325l;
-    long debtSubSubView1 = 96325l;
-    long debtSubSubView2 = 99633l;
-
-    addRawMeasure(TECHNICAL_DEBT_KEY, ROOT_REF, debtRoot);
-    addRawMeasure(TECHNICAL_DEBT_KEY, SUBVIEW_REF, debtSubView);
-    addRawMeasure(TECHNICAL_DEBT_KEY, SUB_SUBVIEW_1_REF, debtSubSubView1);
-    addRawMeasure(TECHNICAL_DEBT_KEY, PROJECT_VIEW_1_REF, 66000l);
-    addRawMeasure(TECHNICAL_DEBT_KEY, PROJECT_VIEW_2_REF, 4200l);
-    addRawMeasure(TECHNICAL_DEBT_KEY, SUB_SUBVIEW_2_REF, debtSubSubView2);
-    addRawMeasure(TECHNICAL_DEBT_KEY, PROJECT_VIEW_3_REF, 25200l);
-    addRawMeasure(TECHNICAL_DEBT_KEY, PROJECT_VIEW_4_REF, 33000l);
-
-    addRawMeasure(DEVELOPMENT_COST_KEY, PROJECT_VIEW_1_REF, "40");
-    addRawMeasure(DEVELOPMENT_COST_KEY, PROJECT_VIEW_2_REF, "70");
-    addRawMeasure(DEVELOPMENT_COST_KEY, PROJECT_VIEW_3_REF, "50");
-    addRawMeasure(DEVELOPMENT_COST_KEY, PROJECT_VIEW_4_REF, "100");
-
-    underTest.visit(treeRootHolder.getRoot());
-
-    assertNoNewRawMeasureOnProjectViews();
-    assertNewRawMeasures(SUB_SUBVIEW_1_REF, debtSubSubView1, 110, D);
-    assertNewRawMeasures(SUB_SUBVIEW_2_REF, debtSubSubView2, 50, E);
-    assertNewRawMeasures(SUBVIEW_REF, debtSubView, 160, D);
-    assertNewRawMeasures(ROOT_REF, debtRoot, 260, B);
-  }
-
-  @Test
-  public void compute_effort_to_maintainability_rating_A_measure() throws Exception {
-    treeRootHolder.setRoot(treeRootHolder.getRoot());
-
-    long projectView1DevCosts = 40L;
-    addRawMeasure(DEVELOPMENT_COST_KEY, PROJECT_VIEW_1_REF, Long.toString(projectView1DevCosts));
-    long projectView2DevCosts = 70L;
-    addRawMeasure(DEVELOPMENT_COST_KEY, PROJECT_VIEW_2_REF, Long.toString(projectView2DevCosts));
-    long projectView3DevCosts = 50L;
-    addRawMeasure(DEVELOPMENT_COST_KEY, PROJECT_VIEW_3_REF, Long.toString(projectView3DevCosts));
-    long projectView4DevCosts = 100L;
-    addRawMeasure(DEVELOPMENT_COST_KEY, PROJECT_VIEW_4_REF, Long.toString(projectView4DevCosts));
-
-    long subSubView1Effort = 10000L;
-    addRawMeasure(TECHNICAL_DEBT_KEY, SUB_SUBVIEW_1_REF, subSubView1Effort);
-
-    long subSubView2Effort = 20000L;
-    addRawMeasure(TECHNICAL_DEBT_KEY, SUB_SUBVIEW_2_REF, subSubView2Effort);
-
-    long subViewEffort = 30000L;
-    addRawMeasure(TECHNICAL_DEBT_KEY, SUBVIEW_REF, subViewEffort);
-
-    long viewEffort = 35000L;
-    addRawMeasure(TECHNICAL_DEBT_KEY, ROOT_REF, viewEffort);
-
-    underTest.visit(treeRootHolder.getRoot());
-
-    verifyRawMeasure(SUB_SUBVIEW_1_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
-      (long) (subSubView1Effort - RATING_GRID[0] * (projectView1DevCosts + projectView2DevCosts)));
-    verifyRawMeasure(SUB_SUBVIEW_2_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
-      (long) (subSubView2Effort - RATING_GRID[0] * projectView3DevCosts));
-    verifyRawMeasure(SUBVIEW_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
-      (long) (subViewEffort - RATING_GRID[0] * (projectView1DevCosts + projectView2DevCosts + projectView3DevCosts)));
-    verifyRawMeasure(ROOT_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
-      (long) (viewEffort - RATING_GRID[0] * (projectView1DevCosts + projectView2DevCosts + projectView3DevCosts +
-        projectView4DevCosts)));
-  }
-
-  private void assertNewRawMeasures(int componentRef, long debt, long devCost, Rating rating) {
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(
-      entryOf(DEVELOPMENT_COST_KEY, newMeasureBuilder().create(String.valueOf(devCost))),
-      entryOf(SQALE_DEBT_RATIO_KEY, newMeasureBuilder().create(debt / (double) devCost * 100.0, 1)),
-      entryOf(SQALE_RATING_KEY, createMaintainabilityRatingMeasure(rating)));
-  }
-
-  private void assertNoNewRawMeasureOnProjectViews() {
-    assertNoNewRawMeasure(PROJECT_VIEW_1_REF);
-    assertNoNewRawMeasure(PROJECT_VIEW_2_REF);
-    assertNoNewRawMeasure(PROJECT_VIEW_3_REF);
-    assertNoNewRawMeasure(PROJECT_VIEW_4_REF);
-  }
-
-  private void addRawMeasure(String metricKey, int componentRef, String value) {
-    measureRepository.addRawMeasure(componentRef, metricKey, newMeasureBuilder().create(value));
-  }
-
-  private void addRawMeasure(String metricKey, int componentRef, long value) {
-    measureRepository.addRawMeasure(componentRef, metricKey, newMeasureBuilder().create(value));
-  }
-
-  private void assertNoNewRawMeasure(int componentRef) {
-    assertThat(measureRepository.getAddedRawMeasures(componentRef).isEmpty()).isTrue();
-  }
-
-  private void verifyRawMeasure(int componentRef, String metricKey, long value) {
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(entryOf(metricKey, newMeasureBuilder().create(value)));
-  }
-
-  private static Measure createMaintainabilityRatingMeasure(Rating rating) {
-    return newMeasureBuilder().create(rating.getIndex(), rating.name());
-  }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitorTest.java
new file mode 100644 (file)
index 0000000..53acf23
--- /dev/null
@@ -0,0 +1,368 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.task.projectanalysis.qualitymodel;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.server.computation.task.projectanalysis.component.Component;
+import org.sonar.server.computation.task.projectanalysis.component.FileAttributes;
+import org.sonar.server.computation.task.projectanalysis.component.ReportComponent;
+import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
+import org.sonar.server.computation.task.projectanalysis.component.VisitorsCrawler;
+import org.sonar.server.computation.task.projectanalysis.issue.ComponentIssuesRepositoryRule;
+import org.sonar.server.computation.task.projectanalysis.measure.Measure;
+import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepositoryRule;
+import org.sonar.server.computation.task.projectanalysis.metric.MetricRepositoryRule;
+import org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating;
+
+import static java.util.Collections.singletonList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.api.measures.CoreMetrics.DEVELOPMENT_COST;
+import static org.sonar.api.measures.CoreMetrics.DEVELOPMENT_COST_KEY;
+import static org.sonar.api.measures.CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A;
+import static org.sonar.api.measures.CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY;
+import static org.sonar.api.measures.CoreMetrics.NCLOC;
+import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY;
+import static org.sonar.api.measures.CoreMetrics.SQALE_DEBT_RATIO;
+import static org.sonar.api.measures.CoreMetrics.SQALE_DEBT_RATIO_KEY;
+import static org.sonar.api.measures.CoreMetrics.SQALE_RATING;
+import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY;
+import static org.sonar.api.measures.CoreMetrics.TECHNICAL_DEBT;
+import static org.sonar.api.measures.CoreMetrics.TECHNICAL_DEBT_KEY;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.DIRECTORY;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.FILE;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.MODULE;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT;
+import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
+import static org.sonar.server.computation.task.projectanalysis.measure.Measure.newMeasureBuilder;
+import static org.sonar.server.computation.task.projectanalysis.measure.MeasureRepoEntry.entryOf;
+import static org.sonar.server.computation.task.projectanalysis.measure.MeasureRepoEntry.toEntries;
+import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.A;
+import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.C;
+import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.E;
+
+public class MaintainabilityMeasuresVisitorTest {
+
+  static final String LANGUAGE_KEY_1 = "lKey1";
+  static final String LANGUAGE_KEY_2 = "lKey2";
+
+  static final double[] RATING_GRID = new double[] {0.1, 0.2, 0.5, 1};
+
+  static final long DEV_COST_LANGUAGE_1 = 30;
+  static final long DEV_COST_LANGUAGE_2 = 42;
+
+  static final int PROJECT_REF = 1;
+  static final int MODULE_REF = 12;
+  static final int DIRECTORY_REF = 123;
+  static final int FILE_1_REF = 1231;
+  static final int FILE_2_REF = 1232;
+
+  static final Component ROOT_PROJECT = builder(Component.Type.PROJECT, PROJECT_REF).setKey("project")
+    .addChildren(
+      builder(MODULE, MODULE_REF).setKey("module")
+        .addChildren(
+          builder(DIRECTORY, DIRECTORY_REF).setKey("directory")
+            .addChildren(
+              builder(FILE, FILE_1_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_KEY_1)).setKey("file1").build(),
+              builder(FILE, FILE_2_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_KEY_1)).setKey("file2").build())
+            .build())
+        .build())
+    .build();
+
+  @Rule
+  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+
+  @Rule
+  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
+    .add(NCLOC)
+    .add(DEVELOPMENT_COST)
+    .add(TECHNICAL_DEBT)
+    .add(SQALE_DEBT_RATIO)
+    .add(SQALE_RATING)
+    .add(EFFORT_TO_REACH_MAINTAINABILITY_RATING_A);
+
+  @Rule
+  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+
+  @Rule
+  public ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
+
+  private RatingSettings ratingSettings = mock(RatingSettings.class);
+
+  private VisitorsCrawler underTest;
+
+  @Before
+  public void setUp() {
+    // assumes rating configuration is consistent
+    when(ratingSettings.getRatingGrid()).thenReturn(new RatingGrid(RATING_GRID));
+    when(ratingSettings.getDevCost(LANGUAGE_KEY_1)).thenReturn(DEV_COST_LANGUAGE_1);
+    when(ratingSettings.getDevCost(LANGUAGE_KEY_2)).thenReturn(DEV_COST_LANGUAGE_2);
+
+    underTest = new VisitorsCrawler(singletonList(new MaintainabilityMeasuresVisitor(metricRepository, measureRepository, ratingSettings)));
+  }
+
+  @Test
+  public void measures_created_for_project_are_all_zero_when_they_have_no_FILE_child() {
+    ReportComponent root = builder(PROJECT, 1).build();
+    treeRootHolder.setRoot(root);
+
+    underTest.visit(root);
+
+    assertThat(toEntries(measureRepository.getRawMeasures(root)))
+      .containsOnly(
+        entryOf(DEVELOPMENT_COST_KEY, newMeasureBuilder().create("0")),
+        entryOf(SQALE_DEBT_RATIO_KEY, newMeasureBuilder().create(0d, 1)),
+        entryOf(SQALE_RATING_KEY, createMaintainabilityRatingMeasure(A)),
+        entryOf(EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY, newMeasureBuilder().create(0L)));
+  }
+
+  @Test
+  public void compute_development_cost() {
+    ReportComponent root = builder(PROJECT, 1)
+      .addChildren(
+        builder(MODULE, 11)
+          .addChildren(
+            builder(DIRECTORY, 111)
+              .addChildren(
+                createFileComponent(LANGUAGE_KEY_1, 1111),
+                createFileComponent(LANGUAGE_KEY_2, 1112),
+                // Unit test should not be ignored
+                builder(FILE, 1113).setFileAttributes(new FileAttributes(true, LANGUAGE_KEY_1)).build())
+              .build(),
+            builder(DIRECTORY, 112)
+              .addChildren(
+                createFileComponent(LANGUAGE_KEY_2, 1121))
+              .build())
+          .build(),
+        builder(MODULE, 12)
+          .addChildren(
+            builder(DIRECTORY, 121)
+              .addChildren(
+                createFileComponent(LANGUAGE_KEY_1, 1211))
+              .build(),
+            builder(DIRECTORY, 122).build())
+          .build(),
+        builder(MODULE, 13).build())
+      .build();
+
+    treeRootHolder.setRoot(root);
+
+    int ncloc1111 = 10;
+    addRawMeasure(NCLOC_KEY, 1111, ncloc1111);
+
+    int ncloc1112 = 12;
+    addRawMeasure(NCLOC_KEY, 1112, ncloc1112);
+
+    int ncloc1113 = 15;
+    addRawMeasure(NCLOC_KEY, 1113, ncloc1113);
+
+    int nclocValue1121 = 30;
+    addRawMeasure(NCLOC_KEY, 1121, nclocValue1121);
+
+    int ncloc1211 = 20;
+    addRawMeasure(NCLOC_KEY, 1211, ncloc1211);
+
+    underTest.visit(root);
+
+    // verify measures on files
+    verifyAddedRawMeasure(1111, DEVELOPMENT_COST_KEY, Long.toString(ncloc1111 * DEV_COST_LANGUAGE_1));
+    verifyAddedRawMeasure(1112, DEVELOPMENT_COST_KEY, Long.toString(ncloc1112 * DEV_COST_LANGUAGE_2));
+    verifyAddedRawMeasure(1113, DEVELOPMENT_COST_KEY, Long.toString(ncloc1113 * DEV_COST_LANGUAGE_1));
+    verifyAddedRawMeasure(1121, DEVELOPMENT_COST_KEY, Long.toString(nclocValue1121 * DEV_COST_LANGUAGE_2));
+    verifyAddedRawMeasure(1211, DEVELOPMENT_COST_KEY, Long.toString(ncloc1211 * DEV_COST_LANGUAGE_1));
+
+    // directory has no children => no file => 0 everywhere and A rating
+    verifyAddedRawMeasure(122, DEVELOPMENT_COST_KEY, "0");
+
+    // directory has children => dev cost is aggregated
+    verifyAddedRawMeasure(111, DEVELOPMENT_COST_KEY, Long.toString(
+      ncloc1111 * DEV_COST_LANGUAGE_1 +
+        ncloc1112 * DEV_COST_LANGUAGE_2 +
+        ncloc1113 * DEV_COST_LANGUAGE_1));
+    verifyAddedRawMeasure(112, DEVELOPMENT_COST_KEY, Long.toString(nclocValue1121 * DEV_COST_LANGUAGE_2));
+    verifyAddedRawMeasure(121, DEVELOPMENT_COST_KEY, Long.toString(ncloc1211 * DEV_COST_LANGUAGE_1));
+
+    // just for fun, we didn't define any debt on module => they must all have rating A
+    verifyAddedRawMeasure(11, DEVELOPMENT_COST_KEY, Long.toString(
+      ncloc1111 * DEV_COST_LANGUAGE_1 +
+        ncloc1112 * DEV_COST_LANGUAGE_2 +
+        ncloc1113 * DEV_COST_LANGUAGE_1 +
+        nclocValue1121 * DEV_COST_LANGUAGE_2));
+    verifyAddedRawMeasure(12, DEVELOPMENT_COST_KEY, Long.toString(ncloc1211 * DEV_COST_LANGUAGE_1));
+    verifyAddedRawMeasure(13, DEVELOPMENT_COST_KEY, "0");
+    verifyAddedRawMeasure(1, DEVELOPMENT_COST_KEY, Long.toString(
+      ncloc1111 * DEV_COST_LANGUAGE_1 +
+        ncloc1112 * DEV_COST_LANGUAGE_2 +
+        ncloc1113 * DEV_COST_LANGUAGE_1 +
+        nclocValue1121 * DEV_COST_LANGUAGE_2 +
+        ncloc1211 * DEV_COST_LANGUAGE_1));
+  }
+
+  @Test
+  public void compute_maintainability_debt_ratio_measure() throws Exception {
+    treeRootHolder.setRoot(ROOT_PROJECT);
+
+    int file1Ncloc = 10;
+    addRawMeasure(NCLOC_KEY, FILE_1_REF, file1Ncloc);
+    long file1MaintainabilityCost = 100L;
+    addRawMeasure(TECHNICAL_DEBT_KEY, FILE_1_REF, file1MaintainabilityCost);
+
+    int file2Ncloc = 5;
+    addRawMeasure(NCLOC_KEY, FILE_2_REF, file2Ncloc);
+    long file2MaintainabilityCost = 1L;
+    addRawMeasure(TECHNICAL_DEBT_KEY, FILE_2_REF, file2MaintainabilityCost);
+
+    long directoryMaintainabilityCost = 100L;
+    addRawMeasure(TECHNICAL_DEBT_KEY, DIRECTORY_REF, directoryMaintainabilityCost);
+
+    long moduleMaintainabilityCost = 100L;
+    addRawMeasure(TECHNICAL_DEBT_KEY, MODULE_REF, moduleMaintainabilityCost);
+
+    long projectMaintainabilityCost = 1000L;
+    addRawMeasure(TECHNICAL_DEBT_KEY, PROJECT_REF, projectMaintainabilityCost);
+
+    underTest.visit(ROOT_PROJECT);
+
+    verifyAddedRawMeasure(FILE_1_REF, SQALE_DEBT_RATIO_KEY, file1MaintainabilityCost * 1d / (file1Ncloc * DEV_COST_LANGUAGE_1) * 100);
+    verifyAddedRawMeasure(FILE_2_REF, SQALE_DEBT_RATIO_KEY, file2MaintainabilityCost * 1d / (file2Ncloc * DEV_COST_LANGUAGE_1) * 100);
+    verifyAddedRawMeasure(DIRECTORY_REF, SQALE_DEBT_RATIO_KEY, directoryMaintainabilityCost * 1d / ((file1Ncloc + file2Ncloc) * DEV_COST_LANGUAGE_1) * 100);
+    verifyAddedRawMeasure(MODULE_REF, SQALE_DEBT_RATIO_KEY, moduleMaintainabilityCost * 1d / ((file1Ncloc + file2Ncloc) * DEV_COST_LANGUAGE_1) * 100);
+    verifyAddedRawMeasure(PROJECT_REF, SQALE_DEBT_RATIO_KEY, projectMaintainabilityCost * 1d / ((file1Ncloc + file2Ncloc) * DEV_COST_LANGUAGE_1) * 100);
+  }
+
+  @Test
+  public void compute_maintainability_rating_measure() throws Exception {
+    treeRootHolder.setRoot(ROOT_PROJECT);
+
+    addRawMeasure(NCLOC_KEY, FILE_1_REF, 10);
+    addRawMeasure(TECHNICAL_DEBT_KEY, FILE_1_REF, 100L);
+
+    addRawMeasure(NCLOC_KEY, FILE_2_REF, 5);
+    addRawMeasure(TECHNICAL_DEBT_KEY, FILE_2_REF, 1L);
+
+    addRawMeasure(TECHNICAL_DEBT_KEY, DIRECTORY_REF, 100L);
+    addRawMeasure(TECHNICAL_DEBT_KEY, MODULE_REF, 100L);
+    addRawMeasure(TECHNICAL_DEBT_KEY, PROJECT_REF, 1000L);
+
+    underTest.visit(ROOT_PROJECT);
+
+    verifyAddedRawMeasure(FILE_1_REF, SQALE_RATING_KEY, C);
+    verifyAddedRawMeasure(FILE_2_REF, SQALE_RATING_KEY, A);
+    verifyAddedRawMeasure(DIRECTORY_REF, SQALE_RATING_KEY, C);
+    verifyAddedRawMeasure(MODULE_REF, SQALE_RATING_KEY, C);
+    verifyAddedRawMeasure(PROJECT_REF, SQALE_RATING_KEY, E);
+  }
+
+  @Test
+  public void compute_effort_to_maintainability_rating_A_measure() throws Exception {
+    treeRootHolder.setRoot(ROOT_PROJECT);
+
+    int file1Ncloc = 10;
+    long file1Effort = 100L;
+    addRawMeasure(NCLOC_KEY, FILE_1_REF, file1Ncloc);
+    addRawMeasure(TECHNICAL_DEBT_KEY, FILE_1_REF, file1Effort);
+
+    int file2Ncloc = 5;
+    long file2Effort = 20L;
+    addRawMeasure(NCLOC_KEY, FILE_2_REF, file2Ncloc);
+    addRawMeasure(TECHNICAL_DEBT_KEY, FILE_2_REF, file2Effort);
+
+    long dirEffort = 120L;
+    addRawMeasure(TECHNICAL_DEBT_KEY, DIRECTORY_REF, dirEffort);
+
+    long moduleEffort = 120L;
+    addRawMeasure(TECHNICAL_DEBT_KEY, MODULE_REF, moduleEffort);
+
+    long projectEffort = 150L;
+    addRawMeasure(TECHNICAL_DEBT_KEY, PROJECT_REF, projectEffort);
+
+    underTest.visit(ROOT_PROJECT);
+
+    verifyAddedRawMeasure(FILE_1_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
+      (long) (file1Effort - RATING_GRID[0] * file1Ncloc * DEV_COST_LANGUAGE_1));
+    verifyAddedRawMeasure(FILE_2_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
+      (long) (file2Effort - RATING_GRID[0] * file2Ncloc * DEV_COST_LANGUAGE_1));
+    verifyAddedRawMeasure(DIRECTORY_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
+      (long) (dirEffort - RATING_GRID[0] * (file1Ncloc + file2Ncloc) * DEV_COST_LANGUAGE_1));
+    verifyAddedRawMeasure(MODULE_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
+      (long) (moduleEffort - RATING_GRID[0] * (file1Ncloc + file2Ncloc) * DEV_COST_LANGUAGE_1));
+    verifyAddedRawMeasure(PROJECT_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
+      (long) (projectEffort - RATING_GRID[0] * (file1Ncloc + file2Ncloc) * DEV_COST_LANGUAGE_1));
+  }
+
+  @Test
+  public void compute_0_effort_to_maintainability_rating_A_when_effort_is_lower_than_dev_cost() throws Exception {
+    treeRootHolder.setRoot(ROOT_PROJECT);
+
+    addRawMeasure(NCLOC_KEY, FILE_1_REF, 10);
+    addRawMeasure(TECHNICAL_DEBT_KEY, FILE_1_REF, 2L);
+
+    underTest.visit(ROOT_PROJECT);
+
+    verifyAddedRawMeasure(FILE_1_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY, 0L);
+  }
+
+  @Test
+  public void effort_to_maintainability_rating_A_is_same_as_effort_when_no_dev_cost() throws Exception {
+    treeRootHolder.setRoot(ROOT_PROJECT);
+
+    addRawMeasure(TECHNICAL_DEBT_KEY, FILE_1_REF, 100L);
+
+    underTest.visit(ROOT_PROJECT);
+
+    verifyAddedRawMeasure(FILE_1_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY, 100);
+  }
+
+  private void addRawMeasure(String metricKey, int componentRef, long value) {
+    measureRepository.addRawMeasure(componentRef, metricKey, newMeasureBuilder().create(value));
+  }
+
+  private void addRawMeasure(String metricKey, int componentRef, int value) {
+    measureRepository.addRawMeasure(componentRef, metricKey, newMeasureBuilder().create(value));
+  }
+
+  private void verifyAddedRawMeasure(int componentRef, String metricKey, long value) {
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(entryOf(metricKey, newMeasureBuilder().create(value)));
+  }
+
+  private void verifyAddedRawMeasure(int componentRef, String metricKey, double value) {
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(entryOf(metricKey, newMeasureBuilder().create(value, 1)));
+  }
+
+  private void verifyAddedRawMeasure(int componentRef, String metricKey, Rating rating) {
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(entryOf(metricKey, newMeasureBuilder().create(rating.getIndex(), rating.name())));
+  }
+
+  private void verifyAddedRawMeasure(int componentRef, String metricKey, String value) {
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(entryOf(metricKey, newMeasureBuilder().create(value)));
+  }
+
+  private static ReportComponent createFileComponent(String languageKey1, int fileRef) {
+    return builder(FILE, fileRef).setFileAttributes(new FileAttributes(false, languageKey1)).build();
+  }
+
+  private static Measure createMaintainabilityRatingMeasure(Rating rating) {
+    return newMeasureBuilder().create(rating.getIndex(), rating.name());
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/ReliabilityAndSecurityRatingMeasuresVisitorForReportTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/ReliabilityAndSecurityRatingMeasuresVisitorForReportTest.java
deleted file mode 100644 (file)
index 7f69d94..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.task.projectanalysis.qualitymodel;
-
-import java.util.Arrays;
-import java.util.Date;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.rules.RuleType;
-import org.sonar.api.utils.Duration;
-import org.sonar.core.issue.DefaultIssue;
-import org.sonar.core.util.Uuids;
-import org.sonar.server.computation.task.projectanalysis.component.Component;
-import org.sonar.server.computation.task.projectanalysis.component.FileAttributes;
-import org.sonar.server.computation.task.projectanalysis.component.ReportComponent;
-import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
-import org.sonar.server.computation.task.projectanalysis.component.VisitorsCrawler;
-import org.sonar.server.computation.task.projectanalysis.issue.ComponentIssuesRepositoryRule;
-import org.sonar.server.computation.task.projectanalysis.issue.FillComponentIssuesVisitorRule;
-import org.sonar.server.computation.task.projectanalysis.measure.Measure;
-import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepositoryRule;
-import org.sonar.server.computation.task.projectanalysis.metric.MetricRepositoryRule;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
-import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING;
-import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING_KEY;
-import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING;
-import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING_KEY;
-import static org.sonar.api.rule.Severity.BLOCKER;
-import static org.sonar.api.rule.Severity.CRITICAL;
-import static org.sonar.api.rule.Severity.INFO;
-import static org.sonar.api.rule.Severity.MAJOR;
-import static org.sonar.api.rule.Severity.MINOR;
-import static org.sonar.api.rules.RuleType.BUG;
-import static org.sonar.api.rules.RuleType.CODE_SMELL;
-import static org.sonar.api.rules.RuleType.VULNERABILITY;
-import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.DIRECTORY;
-import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.FILE;
-import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.MODULE;
-import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT;
-import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
-import static org.sonar.server.computation.task.projectanalysis.measure.Measure.newMeasureBuilder;
-import static org.sonar.server.computation.task.projectanalysis.measure.MeasureRepoEntry.entryOf;
-import static org.sonar.server.computation.task.projectanalysis.measure.MeasureRepoEntry.toEntries;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.A;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.B;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.C;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.D;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.E;
-
-public class ReliabilityAndSecurityRatingMeasuresVisitorForReportTest {
-
-  static final String LANGUAGE_KEY_1 = "lKey1";
-
-  static final int PROJECT_REF = 1;
-  static final int MODULE_REF = 12;
-  static final int DIRECTORY_REF = 123;
-  static final int FILE_1_REF = 1231;
-  static final int FILE_2_REF = 1232;
-
-  static final Component ROOT_PROJECT = builder(Component.Type.PROJECT, PROJECT_REF).setKey("project")
-    .addChildren(
-      builder(MODULE, MODULE_REF).setKey("module")
-        .addChildren(
-          builder(DIRECTORY, DIRECTORY_REF).setKey("directory")
-            .addChildren(
-              builder(FILE, FILE_1_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_KEY_1)).setKey("file1").build(),
-              builder(FILE, FILE_2_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_KEY_1)).setKey("file2").build())
-            .build())
-        .build())
-    .build();
-
-  @Rule
-  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
-
-  @Rule
-  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
-    .add(RELIABILITY_RATING)
-    .add(SECURITY_RATING);
-
-  @Rule
-  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
-
-  @Rule
-  public ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
-
-  @Rule
-  public FillComponentIssuesVisitorRule fillComponentIssuesVisitorRule = new FillComponentIssuesVisitorRule(componentIssuesRepositoryRule, treeRootHolder);
-
-  VisitorsCrawler underTest = new VisitorsCrawler(
-    Arrays.asList(fillComponentIssuesVisitorRule, new ReliabilityAndSecurityRatingMeasuresVisitor(metricRepository, measureRepository, componentIssuesRepositoryRule)));
-
-  @Test
-  public void measures_created_for_project_are_all_A_when_they_have_no_FILE_child() {
-    ReportComponent root = builder(PROJECT, 1).build();
-    treeRootHolder.setRoot(root);
-
-    underTest.visit(root);
-
-    assertThat(toEntries(measureRepository.getRawMeasures(root)))
-      .containsOnly(
-        entryOf(RELIABILITY_RATING_KEY, createRatingMeasure(A)),
-        entryOf(SECURITY_RATING_KEY, createRatingMeasure(A)));
-  }
-
-  @Test
-  public void compute_reliability_rating() throws Exception {
-    treeRootHolder.setRoot(ROOT_PROJECT);
-    fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, MAJOR), newBugIssue(1L, MAJOR),
-      // Should not be taken into account
-      newVulnerabilityIssue(5L, MINOR));
-    fillComponentIssuesVisitorRule.setIssues(FILE_2_REF, newBugIssue(2L, CRITICAL), newBugIssue(3L, MINOR),
-      // Should not be taken into account
-      newBugIssue(10L, BLOCKER).setResolution(RESOLUTION_FIXED));
-    fillComponentIssuesVisitorRule.setIssues(MODULE_REF, newBugIssue(7L, BLOCKER));
-
-    underTest.visit(ROOT_PROJECT);
-
-    verifyAddedRawMeasure(FILE_1_REF, RELIABILITY_RATING_KEY, C);
-    verifyAddedRawMeasure(FILE_2_REF, RELIABILITY_RATING_KEY, D);
-    verifyAddedRawMeasure(DIRECTORY_REF, RELIABILITY_RATING_KEY, D);
-    verifyAddedRawMeasure(MODULE_REF, RELIABILITY_RATING_KEY, E);
-    verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, E);
-  }
-
-  @Test
-  public void compute_security_rating() throws Exception {
-    treeRootHolder.setRoot(ROOT_PROJECT);
-    fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newVulnerabilityIssue(10L, MAJOR), newVulnerabilityIssue(1L, MAJOR),
-      // Should not be taken into account
-      newBugIssue(1L, MAJOR));
-    fillComponentIssuesVisitorRule.setIssues(FILE_2_REF, newVulnerabilityIssue(2L, CRITICAL), newVulnerabilityIssue(3L, MINOR),
-      // Should not be taken into account
-      newVulnerabilityIssue(10L, BLOCKER).setResolution(RESOLUTION_FIXED));
-    fillComponentIssuesVisitorRule.setIssues(MODULE_REF, newVulnerabilityIssue(7L, BLOCKER));
-
-    underTest.visit(ROOT_PROJECT);
-
-    verifyAddedRawMeasure(FILE_1_REF, SECURITY_RATING_KEY, C);
-    verifyAddedRawMeasure(FILE_2_REF, SECURITY_RATING_KEY, D);
-    verifyAddedRawMeasure(DIRECTORY_REF, SECURITY_RATING_KEY, D);
-    verifyAddedRawMeasure(MODULE_REF, SECURITY_RATING_KEY, E);
-    verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, E);
-  }
-
-  @Test
-  public void compute_E_reliability_and_security_rating_on_blocker_issue() throws Exception {
-    treeRootHolder.setRoot(ROOT_PROJECT);
-    fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, BLOCKER), newVulnerabilityIssue(1L, BLOCKER),
-      // Should not be taken into account
-      newBugIssue(1L, MAJOR));
-
-    underTest.visit(ROOT_PROJECT);
-
-    verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, E);
-    verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, E);
-  }
-
-  @Test
-  public void compute_D_reliability_and_security_rating_on_critical_issue() throws Exception {
-    treeRootHolder.setRoot(ROOT_PROJECT);
-    fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, CRITICAL), newVulnerabilityIssue(15L, CRITICAL),
-      // Should not be taken into account
-      newCodeSmellIssue(1L, MAJOR));
-
-    underTest.visit(ROOT_PROJECT);
-
-    verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, D);
-    verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, D);
-  }
-
-  @Test
-  public void compute_C_reliability_and_security_rating_on_major_issue() throws Exception {
-    treeRootHolder.setRoot(ROOT_PROJECT);
-    fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, MAJOR), newVulnerabilityIssue(15L, MAJOR),
-      // Should not be taken into account
-      newCodeSmellIssue(1L, MAJOR));
-
-    underTest.visit(ROOT_PROJECT);
-
-    verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, C);
-    verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, C);
-  }
-
-  @Test
-  public void compute_B_reliability_and_security_rating_on_minor_issue() throws Exception {
-    treeRootHolder.setRoot(ROOT_PROJECT);
-    fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, MINOR), newVulnerabilityIssue(15L, MINOR),
-      // Should not be taken into account
-      newCodeSmellIssue(1L, MAJOR));
-
-    underTest.visit(ROOT_PROJECT);
-
-    verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, B);
-    verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, B);
-  }
-
-  @Test
-  public void compute_A_reliability_and_security_rating_on_info_issue() throws Exception {
-    treeRootHolder.setRoot(ROOT_PROJECT);
-    fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, INFO), newVulnerabilityIssue(15L, INFO),
-      // Should not be taken into account
-      newCodeSmellIssue(1L, MAJOR));
-
-    underTest.visit(ROOT_PROJECT);
-
-    verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, A);
-    verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, A);
-  }
-
-  private void verifyAddedRawMeasure(int componentRef, String metricKey, Rating rating) {
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(entryOf(metricKey, newMeasureBuilder().create(rating.getIndex(), rating.name())));
-  }
-
-  private static Measure createRatingMeasure(Rating rating) {
-    return newMeasureBuilder().create(rating.getIndex(), rating.name());
-  }
-
-  private static DefaultIssue newBugIssue(long effort, String severity) {
-    return newIssue(effort, severity, BUG);
-  }
-
-  private static DefaultIssue newVulnerabilityIssue(long effort, String severity) {
-    return newIssue(effort, severity, VULNERABILITY);
-  }
-
-  private static DefaultIssue newCodeSmellIssue(long effort, String severity) {
-    return newIssue(effort, severity, CODE_SMELL);
-  }
-
-  private static DefaultIssue newIssue(long effort, String severity, RuleType type) {
-    return newIssue(severity, type)
-      .setEffort(Duration.create(effort));
-  }
-
-  private static DefaultIssue newIssue(String severity, RuleType type) {
-    return new DefaultIssue()
-      .setKey(Uuids.create())
-      .setSeverity(severity)
-      .setType(type)
-      .setCreationDate(new Date(1000l));
-  }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/ReliabilityAndSecurityRatingMeasuresVisitorForViewsTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/ReliabilityAndSecurityRatingMeasuresVisitorForViewsTest.java
deleted file mode 100644 (file)
index 905cd52..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.task.projectanalysis.qualitymodel;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
-import org.sonar.server.computation.task.projectanalysis.component.ViewsComponent;
-import org.sonar.server.computation.task.projectanalysis.component.VisitorsCrawler;
-import org.sonar.server.computation.task.projectanalysis.issue.ComponentIssuesRepositoryRule;
-import org.sonar.server.computation.task.projectanalysis.measure.Measure;
-import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepositoryRule;
-import org.sonar.server.computation.task.projectanalysis.metric.MetricRepositoryRule;
-import org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating;
-
-import static java.util.Collections.singletonList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING;
-import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING_KEY;
-import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING;
-import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING_KEY;
-import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT_VIEW;
-import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.SUBVIEW;
-import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.VIEW;
-import static org.sonar.server.computation.task.projectanalysis.component.ViewsComponent.builder;
-import static org.sonar.server.computation.task.projectanalysis.measure.Measure.newMeasureBuilder;
-import static org.sonar.server.computation.task.projectanalysis.measure.MeasureRepoEntry.entryOf;
-import static org.sonar.server.computation.task.projectanalysis.measure.MeasureRepoEntry.toEntries;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.A;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.B;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.C;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.D;
-import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.E;
-
-public class ReliabilityAndSecurityRatingMeasuresVisitorForViewsTest {
-
-  private static final int ROOT_REF = 1;
-  private static final int SUBVIEW_REF = 11;
-  private static final int SUB_SUBVIEW_1_REF = 111;
-  private static final int SUB_SUBVIEW_2_REF = 112;
-  private static final int PROJECT_VIEW_1_REF = 1111;
-  private static final int PROJECT_VIEW_2_REF = 1112;
-  private static final int PROJECT_VIEW_3_REF = 1121;
-  private static final int PROJECT_VIEW_4_REF = 12;
-
-  @Rule
-  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule()
-    .setRoot(builder(VIEW, ROOT_REF)
-      .addChildren(
-        builder(SUBVIEW, SUBVIEW_REF)
-          .addChildren(
-            builder(SUBVIEW, SUB_SUBVIEW_1_REF)
-              .addChildren(
-                builder(PROJECT_VIEW, PROJECT_VIEW_1_REF).build(),
-                builder(PROJECT_VIEW, PROJECT_VIEW_2_REF).build())
-              .build(),
-            builder(SUBVIEW, SUB_SUBVIEW_2_REF)
-              .addChildren(
-                builder(PROJECT_VIEW, PROJECT_VIEW_3_REF).build())
-              .build())
-          .build(),
-        builder(PROJECT_VIEW, PROJECT_VIEW_4_REF).build())
-      .build());
-
-  @Rule
-  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
-    .add(RELIABILITY_RATING)
-    .add(SECURITY_RATING);
-
-  @Rule
-  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
-
-  @Rule
-  public ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
-
-  VisitorsCrawler underTest = new VisitorsCrawler(
-    singletonList(new ReliabilityAndSecurityRatingMeasuresVisitor(metricRepository, measureRepository, componentIssuesRepositoryRule)));
-
-  @Test
-  public void measures_created_for_view_are_all_zero_when_no_child() {
-    ViewsComponent root = builder(VIEW, 1).build();
-    treeRootHolder.setRoot(root);
-
-    underTest.visit(root);
-
-    assertThat(toEntries(measureRepository.getRawMeasures(root)))
-      .containsOnly(
-        entryOf(RELIABILITY_RATING_KEY, createMaintainabilityRatingMeasure(A)),
-        entryOf(SECURITY_RATING_KEY, createMaintainabilityRatingMeasure(A)));
-  }
-
-  @Test
-  public void compute_reliability_rating() throws Exception {
-    treeRootHolder.setRoot(treeRootHolder.getRoot());
-
-    addRawMeasure(RELIABILITY_RATING_KEY, PROJECT_VIEW_1_REF, B);
-    addRawMeasure(RELIABILITY_RATING_KEY, PROJECT_VIEW_2_REF, C);
-    addRawMeasure(RELIABILITY_RATING_KEY, PROJECT_VIEW_3_REF, D);
-    addRawMeasure(RELIABILITY_RATING_KEY, PROJECT_VIEW_4_REF, E);
-
-    underTest.visit(treeRootHolder.getRoot());
-
-    verifyRawMeasure(SUB_SUBVIEW_1_REF, RELIABILITY_RATING_KEY, C);
-    verifyRawMeasure(SUB_SUBVIEW_2_REF, RELIABILITY_RATING_KEY, D);
-    verifyRawMeasure(SUBVIEW_REF, RELIABILITY_RATING_KEY, D);
-    verifyRawMeasure(ROOT_REF, RELIABILITY_RATING_KEY, E);
-  }
-
-  @Test
-  public void compute_security_rating() throws Exception {
-    treeRootHolder.setRoot(treeRootHolder.getRoot());
-
-    addRawMeasure(SECURITY_RATING_KEY, PROJECT_VIEW_2_REF, B);
-    addRawMeasure(SECURITY_RATING_KEY, PROJECT_VIEW_1_REF, C);
-    addRawMeasure(SECURITY_RATING_KEY, PROJECT_VIEW_3_REF, D);
-    addRawMeasure(SECURITY_RATING_KEY, PROJECT_VIEW_4_REF, E);
-
-    underTest.visit(treeRootHolder.getRoot());
-
-    verifyRawMeasure(SUB_SUBVIEW_1_REF, SECURITY_RATING_KEY, C);
-    verifyRawMeasure(SUB_SUBVIEW_2_REF, SECURITY_RATING_KEY, D);
-    verifyRawMeasure(SUBVIEW_REF, SECURITY_RATING_KEY, D);
-    verifyRawMeasure(ROOT_REF, SECURITY_RATING_KEY, E);
-  }
-
-  private void addRawMeasure(String metricKey, int componentRef, Rating value) {
-    measureRepository.addRawMeasure(componentRef, metricKey, newMeasureBuilder().create(value.getIndex(), value.name()));
-  }
-
-  private void verifyRawMeasure(int componentRef, String metricKey, Rating rating) {
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(entryOf(metricKey, newMeasureBuilder().create(rating.getIndex(), rating.name())));
-  }
-
-  private static Measure createMaintainabilityRatingMeasure(Rating rating) {
-    return newMeasureBuilder().create(rating.getIndex(), rating.name());
-  }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/ReliabilityAndSecurityRatingMeasuresVisitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualitymodel/ReliabilityAndSecurityRatingMeasuresVisitorTest.java
new file mode 100644 (file)
index 0000000..8ba41fd
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.task.projectanalysis.qualitymodel;
+
+import java.util.Arrays;
+import java.util.Date;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.rules.RuleType;
+import org.sonar.api.utils.Duration;
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.util.Uuids;
+import org.sonar.server.computation.task.projectanalysis.component.Component;
+import org.sonar.server.computation.task.projectanalysis.component.FileAttributes;
+import org.sonar.server.computation.task.projectanalysis.component.ReportComponent;
+import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
+import org.sonar.server.computation.task.projectanalysis.component.VisitorsCrawler;
+import org.sonar.server.computation.task.projectanalysis.issue.ComponentIssuesRepositoryRule;
+import org.sonar.server.computation.task.projectanalysis.issue.FillComponentIssuesVisitorRule;
+import org.sonar.server.computation.task.projectanalysis.measure.Measure;
+import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepositoryRule;
+import org.sonar.server.computation.task.projectanalysis.metric.MetricRepositoryRule;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
+import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING;
+import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING_KEY;
+import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING;
+import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING_KEY;
+import static org.sonar.api.rule.Severity.BLOCKER;
+import static org.sonar.api.rule.Severity.CRITICAL;
+import static org.sonar.api.rule.Severity.INFO;
+import static org.sonar.api.rule.Severity.MAJOR;
+import static org.sonar.api.rule.Severity.MINOR;
+import static org.sonar.api.rules.RuleType.BUG;
+import static org.sonar.api.rules.RuleType.CODE_SMELL;
+import static org.sonar.api.rules.RuleType.VULNERABILITY;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.DIRECTORY;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.FILE;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.MODULE;
+import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT;
+import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
+import static org.sonar.server.computation.task.projectanalysis.measure.Measure.newMeasureBuilder;
+import static org.sonar.server.computation.task.projectanalysis.measure.MeasureRepoEntry.entryOf;
+import static org.sonar.server.computation.task.projectanalysis.measure.MeasureRepoEntry.toEntries;
+import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating;
+import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.A;
+import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.B;
+import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.C;
+import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.D;
+import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.E;
+
+public class ReliabilityAndSecurityRatingMeasuresVisitorTest {
+
+  static final String LANGUAGE_KEY_1 = "lKey1";
+
+  static final int PROJECT_REF = 1;
+  static final int MODULE_REF = 12;
+  static final int DIRECTORY_REF = 123;
+  static final int FILE_1_REF = 1231;
+  static final int FILE_2_REF = 1232;
+
+  static final Component ROOT_PROJECT = builder(Component.Type.PROJECT, PROJECT_REF).setKey("project")
+    .addChildren(
+      builder(MODULE, MODULE_REF).setKey("module")
+        .addChildren(
+          builder(DIRECTORY, DIRECTORY_REF).setKey("directory")
+            .addChildren(
+              builder(FILE, FILE_1_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_KEY_1)).setKey("file1").build(),
+              builder(FILE, FILE_2_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_KEY_1)).setKey("file2").build())
+            .build())
+        .build())
+    .build();
+
+  @Rule
+  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+
+  @Rule
+  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
+    .add(RELIABILITY_RATING)
+    .add(SECURITY_RATING);
+
+  @Rule
+  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+
+  @Rule
+  public ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
+
+  @Rule
+  public FillComponentIssuesVisitorRule fillComponentIssuesVisitorRule = new FillComponentIssuesVisitorRule(componentIssuesRepositoryRule, treeRootHolder);
+
+  VisitorsCrawler underTest = new VisitorsCrawler(
+    Arrays.asList(fillComponentIssuesVisitorRule, new ReliabilityAndSecurityRatingMeasuresVisitor(metricRepository, measureRepository, componentIssuesRepositoryRule)));
+
+  @Test
+  public void measures_created_for_project_are_all_A_when_they_have_no_FILE_child() {
+    ReportComponent root = builder(PROJECT, 1).build();
+    treeRootHolder.setRoot(root);
+
+    underTest.visit(root);
+
+    assertThat(toEntries(measureRepository.getRawMeasures(root)))
+      .containsOnly(
+        entryOf(RELIABILITY_RATING_KEY, createRatingMeasure(A)),
+        entryOf(SECURITY_RATING_KEY, createRatingMeasure(A)));
+  }
+
+  @Test
+  public void compute_reliability_rating() throws Exception {
+    treeRootHolder.setRoot(ROOT_PROJECT);
+    fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, MAJOR), newBugIssue(1L, MAJOR),
+      // Should not be taken into account
+      newVulnerabilityIssue(5L, MINOR));
+    fillComponentIssuesVisitorRule.setIssues(FILE_2_REF, newBugIssue(2L, CRITICAL), newBugIssue(3L, MINOR),
+      // Should not be taken into account
+      newBugIssue(10L, BLOCKER).setResolution(RESOLUTION_FIXED));
+    fillComponentIssuesVisitorRule.setIssues(MODULE_REF, newBugIssue(7L, BLOCKER));
+
+    underTest.visit(ROOT_PROJECT);
+
+    verifyAddedRawMeasure(FILE_1_REF, RELIABILITY_RATING_KEY, C);
+    verifyAddedRawMeasure(FILE_2_REF, RELIABILITY_RATING_KEY, D);
+    verifyAddedRawMeasure(DIRECTORY_REF, RELIABILITY_RATING_KEY, D);
+    verifyAddedRawMeasure(MODULE_REF, RELIABILITY_RATING_KEY, E);
+    verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, E);
+  }
+
+  @Test
+  public void compute_security_rating() throws Exception {
+    treeRootHolder.setRoot(ROOT_PROJECT);
+    fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newVulnerabilityIssue(10L, MAJOR), newVulnerabilityIssue(1L, MAJOR),
+      // Should not be taken into account
+      newBugIssue(1L, MAJOR));
+    fillComponentIssuesVisitorRule.setIssues(FILE_2_REF, newVulnerabilityIssue(2L, CRITICAL), newVulnerabilityIssue(3L, MINOR),
+      // Should not be taken into account
+      newVulnerabilityIssue(10L, BLOCKER).setResolution(RESOLUTION_FIXED));
+    fillComponentIssuesVisitorRule.setIssues(MODULE_REF, newVulnerabilityIssue(7L, BLOCKER));
+
+    underTest.visit(ROOT_PROJECT);
+
+    verifyAddedRawMeasure(FILE_1_REF, SECURITY_RATING_KEY, C);
+    verifyAddedRawMeasure(FILE_2_REF, SECURITY_RATING_KEY, D);
+    verifyAddedRawMeasure(DIRECTORY_REF, SECURITY_RATING_KEY, D);
+    verifyAddedRawMeasure(MODULE_REF, SECURITY_RATING_KEY, E);
+    verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, E);
+  }
+
+  @Test
+  public void compute_E_reliability_and_security_rating_on_blocker_issue() throws Exception {
+    treeRootHolder.setRoot(ROOT_PROJECT);
+    fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, BLOCKER), newVulnerabilityIssue(1L, BLOCKER),
+      // Should not be taken into account
+      newBugIssue(1L, MAJOR));
+
+    underTest.visit(ROOT_PROJECT);
+
+    verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, E);
+    verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, E);
+  }
+
+  @Test
+  public void compute_D_reliability_and_security_rating_on_critical_issue() throws Exception {
+    treeRootHolder.setRoot(ROOT_PROJECT);
+    fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, CRITICAL), newVulnerabilityIssue(15L, CRITICAL),
+      // Should not be taken into account
+      newCodeSmellIssue(1L, MAJOR));
+
+    underTest.visit(ROOT_PROJECT);
+
+    verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, D);
+    verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, D);
+  }
+
+  @Test
+  public void compute_C_reliability_and_security_rating_on_major_issue() throws Exception {
+    treeRootHolder.setRoot(ROOT_PROJECT);
+    fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, MAJOR), newVulnerabilityIssue(15L, MAJOR),
+      // Should not be taken into account
+      newCodeSmellIssue(1L, MAJOR));
+
+    underTest.visit(ROOT_PROJECT);
+
+    verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, C);
+    verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, C);
+  }
+
+  @Test
+  public void compute_B_reliability_and_security_rating_on_minor_issue() throws Exception {
+    treeRootHolder.setRoot(ROOT_PROJECT);
+    fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, MINOR), newVulnerabilityIssue(15L, MINOR),
+      // Should not be taken into account
+      newCodeSmellIssue(1L, MAJOR));
+
+    underTest.visit(ROOT_PROJECT);
+
+    verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, B);
+    verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, B);
+  }
+
+  @Test
+  public void compute_A_reliability_and_security_rating_on_info_issue() throws Exception {
+    treeRootHolder.setRoot(ROOT_PROJECT);
+    fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, INFO), newVulnerabilityIssue(15L, INFO),
+      // Should not be taken into account
+      newCodeSmellIssue(1L, MAJOR));
+
+    underTest.visit(ROOT_PROJECT);
+
+    verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, A);
+    verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, A);
+  }
+
+  private void verifyAddedRawMeasure(int componentRef, String metricKey, Rating rating) {
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(entryOf(metricKey, newMeasureBuilder().create(rating.getIndex(), rating.name())));
+  }
+
+  private static Measure createRatingMeasure(Rating rating) {
+    return newMeasureBuilder().create(rating.getIndex(), rating.name());
+  }
+
+  private static DefaultIssue newBugIssue(long effort, String severity) {
+    return newIssue(effort, severity, BUG);
+  }
+
+  private static DefaultIssue newVulnerabilityIssue(long effort, String severity) {
+    return newIssue(effort, severity, VULNERABILITY);
+  }
+
+  private static DefaultIssue newCodeSmellIssue(long effort, String severity) {
+    return newIssue(effort, severity, CODE_SMELL);
+  }
+
+  private static DefaultIssue newIssue(long effort, String severity, RuleType type) {
+    return newIssue(severity, type)
+      .setEffort(Duration.create(effort));
+  }
+
+  private static DefaultIssue newIssue(String severity, RuleType type) {
+    return new DefaultIssue()
+      .setKey(Uuids.create())
+      .setSeverity(severity)
+      .setType(type)
+      .setCreationDate(new Date(1000l));
+  }
+
+}