]> source.dussan.org Git - sonarqube.git/commitdiff
Improve unit test coverage
authorJulien HENRY <julien.henry@sonarsource.com>
Tue, 17 May 2016 09:42:45 +0000 (11:42 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Tue, 17 May 2016 12:38:49 +0000 (14:38 +0200)
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/LineMeasureSensor.java [new file with mode: 0644]
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SymbolReferencesSensor.java
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SyntaxHighlightingSensor.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/MeasureSensorTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/MockAnalysisMode.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/MockAnalysisModeTest.java [new file with mode: 0644]
sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/symbol/internal/DefaultSymbolTableTest.java [new file with mode: 0644]
sonar-scanner-engine/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java

index 74699697e874fc4b675101950827b48a25f9c747..38127ef52a3245c6c1665a3d5d8d74d82ab6efa1 100644 (file)
@@ -26,6 +26,7 @@ import org.sonar.xoo.coverage.UtCoverageSensor;
 import org.sonar.xoo.extensions.XooPostJob;
 import org.sonar.xoo.extensions.XooProjectBuilder;
 import org.sonar.xoo.lang.CpdTokenizerSensor;
+import org.sonar.xoo.lang.LineMeasureSensor;
 import org.sonar.xoo.lang.MeasureSensor;
 import org.sonar.xoo.lang.SymbolReferencesSensor;
 import org.sonar.xoo.lang.SyntaxHighlightingSensor;
@@ -90,6 +91,7 @@ public class XooPlugin implements Plugin {
       // sensors
       HasTagSensor.class,
       MeasureSensor.class,
+      LineMeasureSensor.class,
       SyntaxHighlightingSensor.class,
       SymbolReferencesSensor.class,
       ChecksSensor.class,
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/LineMeasureSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/LineMeasureSensor.java
new file mode 100644 (file)
index 0000000..f0f9224
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * 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.xoo.lang;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.measure.MetricFinder;
+import org.sonar.api.batch.sensor.Sensor;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.SensorDescriptor;
+import org.sonar.api.measures.FileLinesContext;
+import org.sonar.api.measures.FileLinesContextFactory;
+import org.sonar.api.utils.KeyValueFormat;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.xoo.Xoo;
+
+/**
+ * Parse files *.xoo.measures
+ */
+public class LineMeasureSensor implements Sensor {
+
+  private static final Logger LOG = Loggers.get(LineMeasureSensor.class);
+
+  private static final String MEASURES_EXTENSION = ".linemeasures";
+
+  private MetricFinder metricFinder;
+
+  private FileLinesContextFactory contextFactory;
+
+  public LineMeasureSensor(FileLinesContextFactory contextFactory) {
+    this.contextFactory = contextFactory;
+    this.metricFinder = metricFinder;
+  }
+
+  private void processFileMeasures(InputFile inputFile, SensorContext context) {
+    File ioFile = inputFile.file();
+    File measureFile = new File(ioFile.getParentFile(), ioFile.getName() + MEASURES_EXTENSION);
+    if (measureFile.exists()) {
+      LOG.debug("Processing " + measureFile.getAbsolutePath());
+      try {
+        FileLinesContext linesContext = contextFactory.createFor(inputFile);
+        List<String> lines = FileUtils.readLines(measureFile, context.fileSystem().encoding().name());
+        int lineNumber = 0;
+        for (String line : lines) {
+          lineNumber++;
+          if (StringUtils.isBlank(line) || line.startsWith("#")) {
+            continue;
+          }
+          processMeasure(inputFile, linesContext, measureFile, lineNumber, line);
+        }
+        linesContext.save();
+      } catch (IOException e) {
+        throw new IllegalStateException(e);
+      }
+    }
+  }
+
+  private void processMeasure(InputFile inputFile, FileLinesContext context, File measureFile, int lineNumber, String line) {
+    try {
+      String metricKey = StringUtils.substringBefore(line, ":");
+      String value = line.substring(metricKey.length() + 1);
+      saveMeasure(context, inputFile, metricKey, KeyValueFormat.parseIntInt(value));
+    } catch (Exception e) {
+      LOG.error("Error processing line " + lineNumber + " of file " + measureFile.getAbsolutePath(), e);
+      throw new IllegalStateException("Error processing line " + lineNumber + " of file " + measureFile.getAbsolutePath(), e);
+    }
+  }
+
+  private void saveMeasure(FileLinesContext context, InputFile xooFile, String metricKey, Map<Integer, Integer> values) {
+    for (Map.Entry<Integer, Integer> entry : values.entrySet()) {
+      context.setIntValue(metricKey, entry.getKey(), entry.getValue());
+    }
+  }
+
+  @Override
+  public void describe(SensorDescriptor descriptor) {
+    descriptor
+      .name("Xoo Line Measure Sensor")
+      .onlyOnLanguages(Xoo.KEY);
+  }
+
+  @Override
+  public void execute(SensorContext context) {
+    for (InputFile file : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguages(Xoo.KEY))) {
+      processFileMeasures(file, context);
+    }
+  }
+}
index 7eb71225771181ac801252f5306be4001c03ea72..a3c4cb9de466e564973b9056b5ac95843fce7e84 100644 (file)
@@ -42,16 +42,16 @@ import org.sonar.xoo.Xoo;
  */
 public class SymbolReferencesSensor implements Sensor {
 
+  private static final Logger LOG = Loggers.get(SymbolReferencesSensor.class);
+
+  private static final String SYMBOL_EXTENSION = ".symbol";
+
   private ResourcePerspectives perspectives;
 
   public SymbolReferencesSensor(ResourcePerspectives perspectives) {
     this.perspectives = perspectives;
   }
 
-  private static final Logger LOG = Loggers.get(SymbolReferencesSensor.class);
-
-  private static final String SYMBOL_EXTENSION = ".symbol";
-
   private void processFileSymbol(InputFile inputFile, SensorContext context) {
     File ioFile = inputFile.file();
     File symbolFile = new File(ioFile.getParentFile(), ioFile.getName() + SYMBOL_EXTENSION);
index e0d2832838218c34f0c2c214593c1efbe7ac584a..f8cad18eefee173a3d3dc161eedddd88feb7a03b 100644 (file)
@@ -30,8 +30,9 @@ import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.sensor.Sensor;
 import org.sonar.api.batch.sensor.SensorContext;
 import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
-import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+import org.sonar.api.component.ResourcePerspectives;
+import org.sonar.api.source.Highlightable;
+import org.sonar.api.source.Highlightable.HighlightingBuilder;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.xoo.Xoo;
@@ -45,6 +46,12 @@ public class SyntaxHighlightingSensor implements Sensor {
 
   private static final String HIGHLIGHTING_EXTENSION = ".highlighting";
 
+  private final ResourcePerspectives perspectives;
+
+  public SyntaxHighlightingSensor(ResourcePerspectives perspectives) {
+    this.perspectives = perspectives;
+  }
+
   private void processFileHighlighting(InputFile inputFile, SensorContext context) {
     File ioFile = inputFile.file();
     File highlightingFile = new File(ioFile.getParentFile(), ioFile.getName() + HIGHLIGHTING_EXTENSION);
@@ -53,28 +60,30 @@ public class SyntaxHighlightingSensor implements Sensor {
       try {
         List<String> lines = FileUtils.readLines(highlightingFile, context.fileSystem().encoding().name());
         int lineNumber = 0;
-        NewHighlighting highlightingBuilder = context.newHighlighting().onFile(inputFile);
-        for (String line : lines) {
-          lineNumber++;
-          if (StringUtils.isBlank(line) || line.startsWith("#")) {
-            continue;
+        Highlightable highlightable = perspectives.as(Highlightable.class, inputFile);
+        if (highlightable != null) {
+          HighlightingBuilder highlightingBuilder = highlightable.newHighlighting();
+          for (String line : lines) {
+            lineNumber++;
+            if (StringUtils.isBlank(line) || line.startsWith("#")) {
+              continue;
+            }
+            processLine(highlightingFile, lineNumber, highlightingBuilder, line);
           }
-          processLine(highlightingFile, lineNumber, highlightingBuilder, line);
+          highlightingBuilder.done();
         }
-        highlightingBuilder.save();
       } catch (IOException e) {
         throw new IllegalStateException(e);
       }
     }
   }
 
-  private static void processLine(File highlightingFile, int lineNumber, NewHighlighting highlightingBuilder, String line) {
+  private static void processLine(File highlightingFile, int lineNumber, HighlightingBuilder highlightingBuilder, String line) {
     try {
       Iterator<String> split = Splitter.on(":").split(line).iterator();
       int startOffset = Integer.parseInt(split.next());
       int endOffset = Integer.parseInt(split.next());
-      TypeOfText type = TypeOfText.forCssClass(split.next());
-      highlightingBuilder.highlight(startOffset, endOffset, type);
+      highlightingBuilder.highlight(startOffset, endOffset, split.next());
     } catch (Exception e) {
       throw new IllegalStateException("Error processing line " + lineNumber + " of file " + highlightingFile.getAbsolutePath(), e);
     }
index 76198a3ac701751bb713768b7ad5eecd3e37a1fb..8c83a20bd32a430d8f73ad35399b5bcdb0c4e73e 100644 (file)
@@ -33,10 +33,10 @@ public class XooPluginTest {
   public void provide_extensions_for_5_5() {
     Plugin.Context context = new Plugin.Context(V5_5);
     new XooPlugin().define(context);
-    assertThat(context.getExtensions()).hasSize(39).contains(CpdTokenizerSensor.class);
+    assertThat(context.getExtensions()).hasSize(40).contains(CpdTokenizerSensor.class);
 
     context = new Plugin.Context(Version.parse("5.4"));
     new XooPlugin().define(context);
-    assertThat(context.getExtensions()).hasSize(38).doesNotContain(CpdTokenizerSensor.class);
+    assertThat(context.getExtensions()).hasSize(39).doesNotContain(CpdTokenizerSensor.class);
   }
 }
index 7ce2dc972ff6d1c5dbed082b162a906879eac6c4..cfd8be118eb7eda0a4cd30d4782b0535fe12b4b6 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+/*
+builder * 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.xoo.lang;
 
 import java.io.File;
index 0a2b80da4143a82ecc5b459ceeaabbdfaab5f489..f46573a953498c990066cbf3f1080c4be01f15bf 100644 (file)
@@ -27,11 +27,15 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.sensor.highlighting.TypeOfText;
 import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
 import org.sonar.api.batch.sensor.internal.SensorContextTester;
+import org.sonar.api.component.ResourcePerspectives;
+import org.sonar.api.source.Highlightable;
+import org.sonar.api.source.Highlightable.HighlightingBuilder;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 public class SyntaxHighlightingSensorTest {
 
@@ -41,11 +45,13 @@ public class SyntaxHighlightingSensorTest {
   @Rule
   public TemporaryFolder temp = new TemporaryFolder();
   private File baseDir;
+  private ResourcePerspectives perspectives;
 
   @Before
   public void prepare() throws IOException {
     baseDir = temp.newFolder();
-    sensor = new SyntaxHighlightingSensor();
+    perspectives = mock(ResourcePerspectives.class);
+    sensor = new SyntaxHighlightingSensor(perspectives);
     context = SensorContextTester.create(baseDir);
   }
 
@@ -69,9 +75,15 @@ public class SyntaxHighlightingSensorTest {
       .initMetadata(" xoo\nazertyazer\nfoo");
     context.fileSystem().add(inputFile);
 
+    Highlightable highlightable = mock(Highlightable.class);
+    when(perspectives.as(Highlightable.class, inputFile)).thenReturn(highlightable);
+    HighlightingBuilder builder = mock(Highlightable.HighlightingBuilder.class);
+    when(highlightable.newHighlighting()).thenReturn(builder);
+
     sensor.execute(context);
 
-    assertThat(context.highlightingTypeAt("foo:src/foo.xoo", 1, 2)).containsOnly(TypeOfText.KEYWORD);
-    assertThat(context.highlightingTypeAt("foo:src/foo.xoo", 2, 8)).containsOnly(TypeOfText.CPP_DOC);
+    verify(builder).highlight(1, 4, "k");
+    verify(builder).highlight(12, 15, "cppd");
+    verify(builder).done();
   }
 }
index 84980207ca3b7c1e94840129b4d017da78a067a2..9fe6895b334548260f8ea4050ed5e95ad52c58b4 100644 (file)
@@ -22,29 +22,24 @@ package org.sonar.api.batch.sensor.internal;
 import org.sonar.api.batch.AnalysisMode;
 
 public class MockAnalysisMode implements AnalysisMode {
-  private boolean isPreview = false;
-  private boolean isIssues = false;
+  private boolean previewOrIssue = false;
 
   @Override
   public boolean isPreview() {
-    return isPreview;
+    return previewOrIssue;
   }
 
-  public void setPreview(boolean value) {
-    this.isPreview = value;
+  public void setPreviewOrIssue(boolean value) {
+    this.previewOrIssue = value;
   }
 
   @Override
   public boolean isIssues() {
-    return this.isIssues;
-  }
-
-  public void setIssues(boolean issues) {
-    this.isIssues = issues;
+    return this.previewOrIssue;
   }
 
   @Override
   public boolean isPublish() {
-    return !isPreview && !isIssues;
+    return !previewOrIssue;
   }
 }
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/MockAnalysisModeTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/MockAnalysisModeTest.java
new file mode 100644 (file)
index 0000000..bd982d4
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.api.batch.sensor.internal;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class MockAnalysisModeTest {
+
+  @Test
+  public void sanityCheck() {
+    MockAnalysisMode mode = new MockAnalysisMode();
+    assertThat(mode.isIssues()).isFalse();
+    assertThat(mode.isPreview()).isFalse();
+    assertThat(mode.isPublish()).isTrue();
+    mode.setPreviewOrIssue(true);
+    assertThat(mode.isIssues()).isTrue();
+    assertThat(mode.isPreview()).isTrue();
+    assertThat(mode.isPublish()).isFalse();
+  }
+
+}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/symbol/internal/DefaultSymbolTableTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/symbol/internal/DefaultSymbolTableTest.java
new file mode 100644 (file)
index 0000000..ee7ba4c
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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.api.batch.sensor.symbol.internal;
+
+import java.util.Map;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class DefaultSymbolTableTest {
+
+  private static final DefaultInputFile INPUT_FILE = new DefaultInputFile("foo", "src/Foo.java")
+    .setLines(2)
+    .setOriginalLineOffsets(new int[] {0, 50})
+    .setLastValidOffset(100);
+
+  private Map<TextRange, Set<TextRange>> referencesPerSymbol;
+
+  @Rule
+  public ExpectedException throwable = ExpectedException.none();
+
+  @Before
+  public void setUpSampleSymbols() {
+
+    DefaultSymbolTable symbolTableBuilder = new DefaultSymbolTable(mock(SensorStorage.class))
+      .onFile(INPUT_FILE);
+    symbolTableBuilder
+      .newSymbol(0, 10)
+      .newReference(12, 15)
+      .newReference(2, 10, 2, 15);
+
+    symbolTableBuilder.newSymbol(1, 12, 1, 15).newReference(52, 55);
+
+    symbolTableBuilder.save();
+
+    referencesPerSymbol = symbolTableBuilder.getReferencesBySymbol();
+  }
+
+  @Test
+  public void should_register_symbols() {
+    assertThat(referencesPerSymbol).hasSize(2);
+  }
+
+}
index 0affd4dad8e0ea62d5fe80cf9dcbbcf913c1dfb2..00e7ee34ab53de7a43467b9af7d829b0f1c4ed6e 100644 (file)
@@ -125,4 +125,30 @@ public class MeasuresMediumTest {
       .contains(tuple("lines", 3), tuple("ncloc", 2));
   }
 
+  @Test
+  public void lineMeasures() throws IOException {
+    File xooFile = new File(srcDir, "sample.xoo");
+    FileUtils.write(xooFile, "Sample xoo\n\n\ncontent");
+
+    File lineMeasures = new File(srcDir, "sample.xoo.linemeasures");
+    FileUtils.write(lineMeasures, "ncloc_data:1=1;2=0;4=1");
+
+    TaskResult result = tester.newTask()
+      .properties(ImmutableMap.<String, String>builder()
+        .put("sonar.task", "scan")
+        .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
+        .put("sonar.projectKey", "com.foo.project")
+        .put("sonar.projectName", "Foo Project")
+        .put("sonar.projectVersion", "1.0-SNAPSHOT")
+        .put("sonar.projectDescription", "Description of Foo Project")
+        .put("sonar.sources", "src")
+        .build())
+      .start();
+
+    Map<String, List<Measure>> allMeasures = result.allMeasures();
+
+    assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value", "stringValue.value")
+      .containsExactly(tuple("lines", 4, ""), tuple("ncloc_data", 0, "1=1;4=1"));
+  }
+
 }