]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6827 MeasureComputersVisitor should support a views tree
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 2 Sep 2015 16:17:08 +0000 (18:17 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 7 Sep 2015 15:54:18 +0000 (17:54 +0200)
server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureComputersVisitor.java
server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureComputersHolderRule.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureComputersVisitorTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/computation/measure/ReportMeasureComputersVisitorTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/measure/ViewsMeasureComputersVisitorTest.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/ce/measure/Component.java

index 2424ae21c6f9e2a8535cbf6f8ae6254aafe22562..9e2041b136ab5660684f9f9a10c443d020664c32 100644 (file)
@@ -31,6 +31,8 @@ import org.sonar.server.computation.measure.api.MeasureComputerContextImpl;
 import org.sonar.server.computation.measure.api.MeasureComputerWrapper;
 import org.sonar.server.computation.metric.MetricRepository;
 
+import static org.sonar.server.computation.component.Component.Type.FILE;
+import static org.sonar.server.computation.component.Component.Type.SUBVIEW;
 import static org.sonar.server.computation.component.ComponentVisitor.Order.POST_ORDER;
 
 public class MeasureComputersVisitor extends TypeAwareVisitorAdapter {
@@ -46,7 +48,7 @@ public class MeasureComputersVisitor extends TypeAwareVisitorAdapter {
 
   public MeasureComputersVisitor(MetricRepository metricRepository, MeasureRepository measureRepository, SettingsRepository settings,
     MeasureComputersHolder measureComputersHolder, ComponentIssuesRepository componentIssuesRepository) {
-    super(CrawlerDepthLimit.FILE, POST_ORDER);
+    super(CrawlerDepthLimit.reportMaxDepth(FILE).withViewsMaxDepth(SUBVIEW), POST_ORDER);
     this.metricRepository = metricRepository;
     this.measureRepository = measureRepository;
     this.settings = settings;
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureComputersHolderRule.java b/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureComputersHolderRule.java
new file mode 100644 (file)
index 0000000..3dd1e74
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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.measure;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.After;
+import org.junit.rules.ExternalResource;
+import org.sonar.api.ce.measure.MeasureComputer;
+import org.sonar.server.computation.measure.api.MeasureComputerWrapper;
+
+import static java.util.Objects.requireNonNull;
+
+public class MeasureComputersHolderRule extends ExternalResource implements MeasureComputersHolder {
+
+  private final MeasureComputer.MeasureComputerDefinitionContext context;
+
+  private List<MeasureComputerWrapper> measureComputers = new ArrayList<>();
+
+  public MeasureComputersHolderRule(MeasureComputer.MeasureComputerDefinitionContext context) {
+    this.context = context;
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    measureComputers.clear();
+  }
+
+  @Override
+  public Iterable<MeasureComputerWrapper> getMeasureComputers() {
+    return measureComputers;
+  }
+
+  public void addMeasureComputer(MeasureComputer measureComputer) {
+    requireNonNull(measureComputer, "Measure computer cannot be null");
+    MeasureComputer.MeasureComputerDefinition definition = measureComputer.define(context);
+    this.measureComputers.add(new MeasureComputerWrapper(measureComputer, definition));
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureComputersVisitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureComputersVisitorTest.java
deleted file mode 100644 (file)
index da69943..0000000
+++ /dev/null
@@ -1,169 +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.measure;
-
-import java.util.Arrays;
-import java.util.Collections;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.ce.measure.MeasureComputer;
-import org.sonar.server.computation.batch.TreeRootHolderRule;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.ComponentVisitor;
-import org.sonar.server.computation.component.VisitorsCrawler;
-import org.sonar.server.computation.issue.ComponentIssuesRepository;
-import org.sonar.server.computation.measure.api.MeasureComputerDefinitionImpl;
-import org.sonar.server.computation.measure.api.MeasureComputerWrapper;
-import org.sonar.server.computation.metric.MetricRepositoryRule;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES;
-import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES_KEY;
-import static org.sonar.api.measures.CoreMetrics.NCLOC;
-import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY;
-import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
-import static org.sonar.server.computation.component.Component.Type.FILE;
-import static org.sonar.server.computation.component.Component.Type.MODULE;
-import static org.sonar.server.computation.component.Component.Type.PROJECT;
-import static org.sonar.server.computation.component.ReportComponent.builder;
-import static org.sonar.server.computation.measure.Measure.newMeasureBuilder;
-import static org.sonar.server.computation.measure.MeasureRepoEntry.entryOf;
-import static org.sonar.server.computation.measure.MeasureRepoEntry.toEntries;
-
-public class MeasureComputersVisitorTest {
-
-  private static final String NEW_METRIC_KEY = "new_metric_key";
-  private static final String NEW_METRIC_NAME = "new metric name";
-
-  private static final org.sonar.api.measures.Metric<Integer> NEW_METRIC = new org.sonar.api.measures.Metric.Builder(NEW_METRIC_KEY, NEW_METRIC_NAME,
-    org.sonar.api.measures.Metric.ValueType.INT)
-    .create();
-
-  private static final int ROOT_REF = 1;
-  private static final int MODULE_REF = 12;
-  private static final int DIRECTORY_REF = 123;
-  private static final int FILE_1_REF = 1231;
-  private static final int FILE_2_REF = 1232;
-
-  private static final Component ROOT = builder(PROJECT, ROOT_REF).setKey("project")
-    .addChildren(
-      builder(MODULE, MODULE_REF).setKey("module")
-        .addChildren(
-          builder(DIRECTORY, DIRECTORY_REF).setKey("directory")
-            .addChildren(
-              builder(FILE, FILE_1_REF).setKey("file1").build(),
-              builder(FILE, FILE_2_REF).setKey("file2").build()
-            ).build()
-        ).build()
-    ).build();
-
-  @Rule
-  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule().setRoot(ROOT);
-
-  @Rule
-  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
-    .add(NCLOC)
-    .add(COMMENT_LINES)
-    .add(NEW_METRIC);
-
-  @Rule
-  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(ROOT, metricRepository);
-
-  ComponentIssuesRepository componentIssuesRepository = mock(ComponentIssuesRepository.class);
-
-  MeasureComputersHolderImpl measureComputersHolder = new MeasureComputersHolderImpl();
-
-  @Test
-  public void compute_plugin_measure() throws Exception {
-    measureRepository.addRawMeasure(FILE_1_REF, NCLOC_KEY, newMeasureBuilder().create(10));
-    measureRepository.addRawMeasure(FILE_1_REF, COMMENT_LINES_KEY, newMeasureBuilder().create(2));
-    measureRepository.addRawMeasure(FILE_2_REF, NCLOC_KEY, newMeasureBuilder().create(40));
-    measureRepository.addRawMeasure(FILE_2_REF, COMMENT_LINES_KEY, newMeasureBuilder().create(5));
-    measureRepository.addRawMeasure(DIRECTORY_REF, NCLOC_KEY, newMeasureBuilder().create(50));
-    measureRepository.addRawMeasure(DIRECTORY_REF, COMMENT_LINES_KEY, newMeasureBuilder().create(7));
-    measureRepository.addRawMeasure(MODULE_REF, NCLOC_KEY, newMeasureBuilder().create(50));
-    measureRepository.addRawMeasure(MODULE_REF, COMMENT_LINES_KEY, newMeasureBuilder().create(7));
-    measureRepository.addRawMeasure(ROOT_REF, NCLOC_KEY, newMeasureBuilder().create(50));
-    measureRepository.addRawMeasure(ROOT_REF, COMMENT_LINES_KEY, newMeasureBuilder().create(7));
-
-    final MeasureComputer.MeasureComputerDefinition definition = new MeasureComputerDefinitionImpl.BuilderImpl()
-      .setInputMetrics(NCLOC_KEY, COMMENT_LINES_KEY)
-      .setOutputMetrics(NEW_METRIC_KEY)
-      .build();
-    measureComputersHolder.setMeasureComputers(newArrayList(
-      new MeasureComputerWrapper(
-        new MeasureComputer() {
-          @Override
-          public MeasureComputerDefinition define(MeasureComputerDefinitionContext defContext) {
-            return definition;
-          }
-
-          @Override
-          public void compute(MeasureComputerContext context) {
-            org.sonar.api.ce.measure.Measure ncloc = context.getMeasure(NCLOC_KEY);
-            org.sonar.api.ce.measure.Measure comment = context.getMeasure(COMMENT_LINES_KEY);
-            if (ncloc != null && comment != null) {
-              context.addMeasure(NEW_METRIC_KEY, ncloc.getIntValue() + comment.getIntValue());
-            }
-          }
-        },
-        definition
-      )));
-
-    VisitorsCrawler visitorsCrawler = new VisitorsCrawler(Arrays.<ComponentVisitor>asList(new MeasureComputersVisitor(metricRepository, measureRepository, null,
-      measureComputersHolder, componentIssuesRepository)));
-    visitorsCrawler.visit(ROOT);
-
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_1_REF))).containsOnly(entryOf(NEW_METRIC_KEY, newMeasureBuilder().create(12)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_2_REF))).containsOnly(entryOf(NEW_METRIC_KEY, newMeasureBuilder().create(45)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(DIRECTORY_REF))).containsOnly(entryOf(NEW_METRIC_KEY, newMeasureBuilder().create(57)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(MODULE_REF))).containsOnly(entryOf(NEW_METRIC_KEY, newMeasureBuilder().create(57)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(ROOT_REF))).containsOnly(entryOf(NEW_METRIC_KEY, newMeasureBuilder().create(57)));
-  }
-
-  @Test
-  public void nothing_to_compute() throws Exception {
-    measureRepository.addRawMeasure(FILE_1_REF, NCLOC_KEY, newMeasureBuilder().create(10));
-    measureRepository.addRawMeasure(FILE_1_REF, COMMENT_LINES_KEY, newMeasureBuilder().create(2));
-    measureRepository.addRawMeasure(FILE_2_REF, NCLOC_KEY, newMeasureBuilder().create(40));
-    measureRepository.addRawMeasure(FILE_2_REF, COMMENT_LINES_KEY, newMeasureBuilder().create(5));
-    measureRepository.addRawMeasure(DIRECTORY_REF, NCLOC_KEY, newMeasureBuilder().create(50));
-    measureRepository.addRawMeasure(DIRECTORY_REF, COMMENT_LINES_KEY, newMeasureBuilder().create(7));
-    measureRepository.addRawMeasure(MODULE_REF, NCLOC_KEY, newMeasureBuilder().create(50));
-    measureRepository.addRawMeasure(MODULE_REF, COMMENT_LINES_KEY, newMeasureBuilder().create(7));
-    measureRepository.addRawMeasure(ROOT_REF, NCLOC_KEY, newMeasureBuilder().create(50));
-    measureRepository.addRawMeasure(ROOT_REF, COMMENT_LINES_KEY, newMeasureBuilder().create(7));
-
-    measureComputersHolder.setMeasureComputers(Collections.<MeasureComputerWrapper>emptyList());
-    VisitorsCrawler visitorsCrawler = new VisitorsCrawler(Arrays.<ComponentVisitor>asList(new MeasureComputersVisitor(metricRepository, measureRepository, null,
-      measureComputersHolder, componentIssuesRepository)));
-    visitorsCrawler.visit(ROOT);
-
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_1_REF))).isEmpty();
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_2_REF))).isEmpty();
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(DIRECTORY_REF))).isEmpty();
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(MODULE_REF))).isEmpty();
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(ROOT_REF))).isEmpty();
-  }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/measure/ReportMeasureComputersVisitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/measure/ReportMeasureComputersVisitorTest.java
new file mode 100644 (file)
index 0000000..4620876
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * 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.measure;
+
+import java.util.Arrays;
+import java.util.Collections;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.ce.measure.MeasureComputer;
+import org.sonar.server.computation.batch.TreeRootHolderRule;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.ComponentVisitor;
+import org.sonar.server.computation.component.VisitorsCrawler;
+import org.sonar.server.computation.issue.ComponentIssuesRepository;
+import org.sonar.server.computation.measure.api.MeasureComputerDefinitionImpl;
+import org.sonar.server.computation.measure.api.MeasureComputerWrapper;
+import org.sonar.server.computation.metric.MetricRepositoryRule;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES;
+import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES_KEY;
+import static org.sonar.api.measures.CoreMetrics.NCLOC;
+import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY;
+import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
+import static org.sonar.server.computation.component.Component.Type.FILE;
+import static org.sonar.server.computation.component.Component.Type.MODULE;
+import static org.sonar.server.computation.component.Component.Type.PROJECT;
+import static org.sonar.server.computation.component.ReportComponent.builder;
+import static org.sonar.server.computation.measure.Measure.newMeasureBuilder;
+import static org.sonar.server.computation.measure.MeasureRepoEntry.entryOf;
+import static org.sonar.server.computation.measure.MeasureRepoEntry.toEntries;
+
+public class ReportMeasureComputersVisitorTest {
+
+  private static final String NEW_METRIC_KEY = "new_metric_key";
+  private static final String NEW_METRIC_NAME = "new metric name";
+
+  private static final org.sonar.api.measures.Metric<Integer> NEW_METRIC = new org.sonar.api.measures.Metric.Builder(NEW_METRIC_KEY, NEW_METRIC_NAME,
+    org.sonar.api.measures.Metric.ValueType.INT)
+    .create();
+
+  private static final int ROOT_REF = 1;
+  private static final int MODULE_REF = 12;
+  private static final int DIRECTORY_REF = 123;
+  private static final int FILE_1_REF = 1231;
+  private static final int FILE_2_REF = 1232;
+
+  private static final Component ROOT = builder(PROJECT, ROOT_REF).setKey("project")
+    .addChildren(
+      builder(MODULE, MODULE_REF).setKey("module")
+        .addChildren(
+          builder(DIRECTORY, DIRECTORY_REF).setKey("directory")
+            .addChildren(
+              builder(FILE, FILE_1_REF).setKey("file1").build(),
+              builder(FILE, FILE_2_REF).setKey("file2").build()
+            ).build()
+        ).build()
+    ).build();
+
+  @Rule
+  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule().setRoot(ROOT);
+
+  @Rule
+  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
+    .add(NCLOC)
+    .add(COMMENT_LINES)
+    .add(NEW_METRIC);
+
+  @Rule
+  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(ROOT, metricRepository);
+
+  ComponentIssuesRepository componentIssuesRepository = mock(ComponentIssuesRepository.class);
+
+  MeasureComputersHolderImpl measureComputersHolder = new MeasureComputersHolderImpl();
+
+  @Test
+  public void compute_plugin_measure() throws Exception {
+    addRawMeasure(FILE_1_REF, NCLOC_KEY, 10);
+    addRawMeasure(FILE_1_REF, COMMENT_LINES_KEY, 2);
+    addRawMeasure(FILE_2_REF, NCLOC_KEY, 40);
+    addRawMeasure(FILE_2_REF, COMMENT_LINES_KEY, 5);
+    addRawMeasure(DIRECTORY_REF, NCLOC_KEY, 50);
+    addRawMeasure(DIRECTORY_REF, COMMENT_LINES_KEY, 7);
+    addRawMeasure(MODULE_REF, NCLOC_KEY, 50);
+    addRawMeasure(MODULE_REF, COMMENT_LINES_KEY, 7);
+    addRawMeasure(ROOT_REF, NCLOC_KEY, 50);
+    addRawMeasure(ROOT_REF, COMMENT_LINES_KEY, 7);
+
+    final MeasureComputer.MeasureComputerDefinition definition = new MeasureComputerDefinitionImpl.BuilderImpl()
+      .setInputMetrics(NCLOC_KEY, COMMENT_LINES_KEY)
+      .setOutputMetrics(NEW_METRIC_KEY)
+      .build();
+    measureComputersHolder.setMeasureComputers(newArrayList(
+      new MeasureComputerWrapper(
+        new MeasureComputer() {
+          @Override
+          public MeasureComputerDefinition define(MeasureComputerDefinitionContext defContext) {
+            return definition;
+          }
+
+          @Override
+          public void compute(MeasureComputerContext context) {
+            org.sonar.api.ce.measure.Measure ncloc = context.getMeasure(NCLOC_KEY);
+            org.sonar.api.ce.measure.Measure comment = context.getMeasure(COMMENT_LINES_KEY);
+            if (ncloc != null && comment != null) {
+              context.addMeasure(NEW_METRIC_KEY, ncloc.getIntValue() + comment.getIntValue());
+            }
+          }
+        },
+        definition
+      )));
+
+    VisitorsCrawler visitorsCrawler = new VisitorsCrawler(Arrays.<ComponentVisitor>asList(new MeasureComputersVisitor(metricRepository, measureRepository, null,
+      measureComputersHolder, componentIssuesRepository)));
+    visitorsCrawler.visit(ROOT);
+
+    assertAddedRawMeasure(12, FILE_1_REF, NEW_METRIC_KEY);
+    assertAddedRawMeasure(45, FILE_2_REF, NEW_METRIC_KEY);
+    assertAddedRawMeasure(57, DIRECTORY_REF, NEW_METRIC_KEY);
+    assertAddedRawMeasure(57, MODULE_REF, NEW_METRIC_KEY);
+    assertAddedRawMeasure(57, ROOT_REF, NEW_METRIC_KEY);
+  }
+
+  @Test
+  public void nothing_to_compute() throws Exception {
+    addRawMeasure(FILE_1_REF, NCLOC_KEY, 10);
+    addRawMeasure(FILE_1_REF, COMMENT_LINES_KEY, 2);
+    addRawMeasure(FILE_2_REF, NCLOC_KEY, 40);
+    addRawMeasure(FILE_2_REF, COMMENT_LINES_KEY, 5);
+    addRawMeasure(DIRECTORY_REF, NCLOC_KEY, 50);
+    addRawMeasure(DIRECTORY_REF, COMMENT_LINES_KEY, 7);
+    addRawMeasure(MODULE_REF, NCLOC_KEY, 50);
+    addRawMeasure(MODULE_REF, COMMENT_LINES_KEY, 7);
+    addRawMeasure(ROOT_REF, NCLOC_KEY, 50);
+    addRawMeasure(ROOT_REF, COMMENT_LINES_KEY, 7);
+
+    measureComputersHolder.setMeasureComputers(Collections.<MeasureComputerWrapper>emptyList());
+    VisitorsCrawler visitorsCrawler = new VisitorsCrawler(Arrays.<ComponentVisitor>asList(new MeasureComputersVisitor(metricRepository, measureRepository, null,
+      measureComputersHolder, componentIssuesRepository)));
+    visitorsCrawler.visit(ROOT);
+
+    assertNoAddedRawMeasure(FILE_1_REF);
+    assertNoAddedRawMeasure(FILE_2_REF);
+    assertNoAddedRawMeasure(DIRECTORY_REF);
+    assertNoAddedRawMeasure(MODULE_REF);
+    assertNoAddedRawMeasure(ROOT_REF);
+  }
+
+  private void addRawMeasure(int componentRef, String metricKey, int value) {
+    measureRepository.addRawMeasure(componentRef, metricKey, newMeasureBuilder().create(value));
+  }
+
+  private void assertNoAddedRawMeasure(int componentRef) {
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).isEmpty();
+  }
+
+  private void assertAddedRawMeasure(int value, int componentRef, String metricKey) {
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).containsOnly(entryOf(metricKey, newMeasureBuilder().create(value)));
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/measure/ViewsMeasureComputersVisitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/measure/ViewsMeasureComputersVisitorTest.java
new file mode 100644 (file)
index 0000000..99493cc
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * 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.measure;
+
+import java.util.Arrays;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.ce.measure.MeasureComputer;
+import org.sonar.api.ce.measure.test.TestMeasureComputerDefinitionContext;
+import org.sonar.server.computation.batch.TreeRootHolderRule;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.ComponentVisitor;
+import org.sonar.server.computation.component.VisitorsCrawler;
+import org.sonar.server.computation.issue.ComponentIssuesRepository;
+import org.sonar.server.computation.measure.api.MeasureComputerDefinitionImpl;
+import org.sonar.server.computation.metric.MetricRepositoryRule;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES;
+import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES_KEY;
+import static org.sonar.api.measures.CoreMetrics.NCLOC;
+import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY;
+import static org.sonar.server.computation.component.Component.Type.PROJECT_VIEW;
+import static org.sonar.server.computation.component.Component.Type.SUBVIEW;
+import static org.sonar.server.computation.component.Component.Type.VIEW;
+import static org.sonar.server.computation.component.ViewsComponent.builder;
+import static org.sonar.server.computation.measure.Measure.newMeasureBuilder;
+import static org.sonar.server.computation.measure.MeasureRepoEntry.entryOf;
+import static org.sonar.server.computation.measure.MeasureRepoEntry.toEntries;
+
+public class ViewsMeasureComputersVisitorTest {
+
+  private static final String NEW_METRIC_KEY = "new_metric_key";
+  private static final String NEW_METRIC_NAME = "new metric name";
+
+  private static final org.sonar.api.measures.Metric<Integer> NEW_METRIC = new org.sonar.api.measures.Metric.Builder(NEW_METRIC_KEY, NEW_METRIC_NAME,
+    org.sonar.api.measures.Metric.ValueType.INT)
+    .create();
+
+  private static final int ROOT_REF = 1;
+  private static final int VIEW_REF = 12;
+  private static final int SUB_SUBVIEW_REF = 123;
+  private static final int PROJECT_VIEW_1_REF = 1231;
+  private static final int PROJECT_VIEW_2_REF = 1232;
+
+  private static final Component TREE_WITH_SUB_VIEWS = builder(VIEW, ROOT_REF)
+    .addChildren(
+      builder(SUBVIEW, VIEW_REF)
+        .addChildren(
+          builder(SUBVIEW, SUB_SUBVIEW_REF)
+            .addChildren(
+              builder(PROJECT_VIEW, PROJECT_VIEW_1_REF).build(),
+              builder(PROJECT_VIEW, PROJECT_VIEW_2_REF).build())
+            .build())
+        .build())
+    .build();
+
+  private static final Component TREE_WITH_DIRECT_PROJECT_VIEW = builder(VIEW, ROOT_REF)
+    .addChildren(
+      builder(PROJECT_VIEW, PROJECT_VIEW_1_REF).build(),
+      builder(PROJECT_VIEW, PROJECT_VIEW_2_REF).build())
+    .build();
+
+  private static final MeasureComputer MEASURE_COMPUTER = new MeasureComputer() {
+    @Override
+    public MeasureComputer.MeasureComputerDefinition define(MeasureComputer.MeasureComputerDefinitionContext defContext) {
+      return new MeasureComputerDefinitionImpl.BuilderImpl()
+        .setInputMetrics(NCLOC_KEY, COMMENT_LINES_KEY)
+        .setOutputMetrics(NEW_METRIC_KEY)
+        .build();
+    }
+
+    @Override
+    public void compute(MeasureComputer.MeasureComputerContext context) {
+      org.sonar.api.ce.measure.Measure ncloc = context.getMeasure(NCLOC_KEY);
+      org.sonar.api.ce.measure.Measure comment = context.getMeasure(COMMENT_LINES_KEY);
+      if (ncloc != null && comment != null) {
+        context.addMeasure(NEW_METRIC_KEY, ncloc.getIntValue() + comment.getIntValue());
+      }
+    }
+  };
+
+  @Rule
+  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+
+  @Rule
+  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
+    .add(NCLOC)
+    .add(COMMENT_LINES)
+    .add(NEW_METRIC);
+
+  @Rule
+  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(TREE_WITH_SUB_VIEWS, metricRepository);
+
+  @Rule
+  public MeasureComputersHolderRule measureComputersHolder = new MeasureComputersHolderRule(new TestMeasureComputerDefinitionContext());
+
+  ComponentIssuesRepository componentIssuesRepository = mock(ComponentIssuesRepository.class);
+
+  @Test
+  public void compute_plugin_measure() throws Exception {
+    treeRootHolder.setRoot(TREE_WITH_SUB_VIEWS);
+
+    addRawMeasure(PROJECT_VIEW_1_REF, NCLOC_KEY, 10);
+    addRawMeasure(PROJECT_VIEW_1_REF, COMMENT_LINES_KEY, 2);
+    addRawMeasure(PROJECT_VIEW_2_REF, NCLOC_KEY, 40);
+    addRawMeasure(PROJECT_VIEW_2_REF, COMMENT_LINES_KEY, 5);
+    addRawMeasure(SUB_SUBVIEW_REF, NCLOC_KEY, 50);
+    addRawMeasure(SUB_SUBVIEW_REF, COMMENT_LINES_KEY, 7);
+    addRawMeasure(VIEW_REF, NCLOC_KEY, 50);
+    addRawMeasure(VIEW_REF, COMMENT_LINES_KEY, 7);
+    addRawMeasure(ROOT_REF, NCLOC_KEY, 50);
+    addRawMeasure(ROOT_REF, COMMENT_LINES_KEY, 7);
+
+    measureComputersHolder.addMeasureComputer(MEASURE_COMPUTER);
+
+    VisitorsCrawler visitorsCrawler = new VisitorsCrawler(Arrays.<ComponentVisitor>asList(new MeasureComputersVisitor(metricRepository, measureRepository, null,
+      measureComputersHolder, componentIssuesRepository)));
+    visitorsCrawler.visit(treeRootHolder.getRoot());
+
+    assertNoAddedRawMeasureOnProjectViews();
+    assertAddedRawMeasure(57, SUB_SUBVIEW_REF, NEW_METRIC_KEY);
+    assertAddedRawMeasure(57, VIEW_REF, NEW_METRIC_KEY);
+    assertAddedRawMeasure(57, ROOT_REF, NEW_METRIC_KEY);
+  }
+
+  @Test
+  public void compute_plugin_measure_on_views_tree_having_only_one_view_with_a_project_view() throws Exception {
+    treeRootHolder.setRoot(TREE_WITH_DIRECT_PROJECT_VIEW);
+
+    addRawMeasure(PROJECT_VIEW_1_REF, NCLOC_KEY, 10);
+    addRawMeasure(PROJECT_VIEW_1_REF, COMMENT_LINES_KEY, 2);
+    addRawMeasure(PROJECT_VIEW_2_REF, NCLOC_KEY, 40);
+    addRawMeasure(PROJECT_VIEW_2_REF, COMMENT_LINES_KEY, 5);
+    addRawMeasure(ROOT_REF, NCLOC_KEY, 50);
+    addRawMeasure(ROOT_REF, COMMENT_LINES_KEY, 7);
+
+    measureComputersHolder.addMeasureComputer(MEASURE_COMPUTER);
+
+    VisitorsCrawler visitorsCrawler = new VisitorsCrawler(Arrays.<ComponentVisitor>asList(new MeasureComputersVisitor(metricRepository, measureRepository, null,
+      measureComputersHolder, componentIssuesRepository)));
+    visitorsCrawler.visit(treeRootHolder.getRoot());
+
+    assertNoAddedRawMeasureOnProjectViews();
+    assertAddedRawMeasure(57, ROOT_REF, NEW_METRIC_KEY);
+  }
+
+  @Test
+  public void nothing_to_compute_when_no_project_view() throws Exception {
+    treeRootHolder.setRoot(builder(VIEW, ROOT_REF)
+      .addChildren(
+        builder(SUBVIEW, VIEW_REF)
+          .addChildren(
+            builder(SUBVIEW, SUB_SUBVIEW_REF)
+              .build())
+          .build())
+      .build());
+
+    measureComputersHolder.addMeasureComputer(MEASURE_COMPUTER);
+
+    VisitorsCrawler visitorsCrawler = new VisitorsCrawler(Arrays.<ComponentVisitor>asList(new MeasureComputersVisitor(metricRepository, measureRepository, null,
+      measureComputersHolder, componentIssuesRepository)));
+    visitorsCrawler.visit(treeRootHolder.getRoot());
+
+    assertNoAddedRawMeasureOnProjectViews();
+    assertNoAddedRawMeasure(SUB_SUBVIEW_REF);
+    assertNoAddedRawMeasure(VIEW_REF);
+    assertNoAddedRawMeasure(ROOT_REF);
+  }
+
+  @Test
+  public void nothing_to_compute_when_no_measure_computers() throws Exception {
+    treeRootHolder.setRoot(TREE_WITH_SUB_VIEWS);
+
+    addRawMeasure(PROJECT_VIEW_1_REF, NCLOC_KEY, 10);
+    addRawMeasure(PROJECT_VIEW_1_REF, COMMENT_LINES_KEY, 2);
+    addRawMeasure(PROJECT_VIEW_2_REF, NCLOC_KEY, 40);
+    addRawMeasure(PROJECT_VIEW_2_REF, COMMENT_LINES_KEY, 5);
+    addRawMeasure(SUB_SUBVIEW_REF, NCLOC_KEY, 50);
+    addRawMeasure(SUB_SUBVIEW_REF, COMMENT_LINES_KEY, 7);
+    addRawMeasure(VIEW_REF, NCLOC_KEY, 50);
+    addRawMeasure(VIEW_REF, COMMENT_LINES_KEY, 7);
+    addRawMeasure(ROOT_REF, NCLOC_KEY, 50);
+    addRawMeasure(ROOT_REF, COMMENT_LINES_KEY, 7);
+
+    VisitorsCrawler visitorsCrawler = new VisitorsCrawler(Arrays.<ComponentVisitor>asList(new MeasureComputersVisitor(metricRepository, measureRepository, null,
+      measureComputersHolder, componentIssuesRepository)));
+    visitorsCrawler.visit(treeRootHolder.getRoot());
+
+    assertNoAddedRawMeasureOnProjectViews();
+    assertNoAddedRawMeasure(SUB_SUBVIEW_REF);
+    assertNoAddedRawMeasure(VIEW_REF);
+    assertNoAddedRawMeasure(ROOT_REF);
+  }
+
+  private void assertNoAddedRawMeasureOnProjectViews() {
+    assertNoAddedRawMeasure(PROJECT_VIEW_1_REF);
+    assertNoAddedRawMeasure(PROJECT_VIEW_2_REF);
+  }
+
+  private void addRawMeasure(int componentRef, String metricKey, int value) {
+    measureRepository.addRawMeasure(componentRef, metricKey, newMeasureBuilder().create(value));
+  }
+
+  private void assertNoAddedRawMeasure(int componentRef) {
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).isEmpty();
+  }
+
+  private void assertAddedRawMeasure(int value, int componentRef, String metricKey) {
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).containsOnly(entryOf(metricKey, newMeasureBuilder().create(value)));
+  }
+
+}
index f94098414e942c177d918d7fbd4b957eb7603a42..8aa11e9ec447e313d8588760d90eb2e23886f0b8 100644 (file)
@@ -30,7 +30,7 @@ import javax.annotation.CheckForNull;
 public interface Component {
 
   enum Type {
-    PROJECT, MODULE, DIRECTORY, FILE
+    PROJECT, MODULE, DIRECTORY, FILE, VIEW, SUBVIEW
   }
 
   Type getType();