]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5419 sonar.sources and sonar.tests should support a mixed list of files and...
authorJulien HENRY <julien.henry@sonarsource.com>
Thu, 3 Jul 2014 15:31:17 +0000 (17:31 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Thu, 3 Jul 2014 15:31:56 +0000 (17:31 +0200)
12 files changed:
sonar-batch/src/main/java/org/sonar/batch/mediumtest/AnalyzerMediumTester.java
sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorBuilder.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleFileSystemInitializer.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/fs/FileSystemMediumTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/XooMediumTest.java [deleted file]
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ModuleFileSystemInitializerTest.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java

index c597e96d29c92cc3929219a50c85abaf27ad8237..a141d3c83c43dd14a8d303d51c3589aa8d7716fb 100644 (file)
@@ -28,6 +28,7 @@ import org.sonar.api.SonarPlugin;
 import org.sonar.api.batch.analyzer.issue.AnalyzerIssue;
 import org.sonar.api.batch.analyzer.measure.AnalyzerMeasure;
 import org.sonar.api.batch.debt.internal.DefaultDebtModel;
+import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
 import org.sonar.api.batch.rule.internal.RulesBuilder;
 import org.sonar.api.measures.CoreMetrics;
@@ -45,6 +46,7 @@ import org.sonar.batch.languages.Language;
 import org.sonar.batch.languages.LanguagesReferential;
 import org.sonar.batch.rule.QProfile;
 import org.sonar.batch.rules.QProfilesReferential;
+import org.sonar.batch.scan.filesystem.InputFileCache;
 import org.sonar.batch.scan2.AnalyzerIssueCache;
 import org.sonar.batch.scan2.AnalyzerMeasureCache;
 import org.sonar.batch.scan2.ProjectScanContainer;
@@ -227,6 +229,7 @@ public class AnalyzerMediumTester {
   public static class TaskResult implements ScanTaskObserver {
     private List<AnalyzerIssue> issues = new ArrayList<AnalyzerIssue>();
     private List<AnalyzerMeasure> measures = new ArrayList<AnalyzerMeasure>();
+    private List<InputFile> inputFiles = new ArrayList<InputFile>();
 
     @Override
     public void scanTaskCompleted(ProjectScanContainer container) {
@@ -237,6 +240,11 @@ public class AnalyzerMediumTester {
       for (AnalyzerMeasure<?> measure : container.getComponentByType(AnalyzerMeasureCache.class).all()) {
         measures.add(measure);
       }
+
+      InputFileCache inputFileCache = container.getComponentByType(InputFileCache.class);
+      for (InputFile inputFile : inputFileCache.all()) {
+        inputFiles.add(inputFile);
+      }
     }
 
     public List<AnalyzerIssue> issues() {
@@ -247,6 +255,10 @@ public class AnalyzerMediumTester {
       return measures;
     }
 
+    public List<InputFile> inputFiles() {
+      return inputFiles;
+    }
+
   }
 
   private static class FakeSettingsReferential implements SettingsReferential {
index 027abd427eb77053b22a1429a241afefb23ba31b..68f62cf4e98c19fecfa61be7c7dce76b8c570f6c 100644 (file)
@@ -304,8 +304,8 @@ public class ProjectReactorBuilder {
       }
 
       // Check sonar.tests
-      String[] testDirs = getListFromProperty(props, PROPERTY_TESTS);
-      checkExistenceOfDirectories(projectId, baseDir, testDirs, PROPERTY_TESTS);
+      String[] testPaths = getListFromProperty(props, PROPERTY_TESTS);
+      checkExistenceOfPaths(projectId, baseDir, testPaths, PROPERTY_TESTS);
 
       // Check sonar.binaries
       String[] binDirs = getListFromProperty(props, PROPERTY_BINARIES);
@@ -332,8 +332,8 @@ public class ProjectReactorBuilder {
     Properties properties = project.getProperties();
 
     // We need to check the existence of source directories
-    String[] sourceDirs = getListFromProperty(properties, PROPERTY_SOURCES);
-    checkExistenceOfDirectories(project.getKey(), project.getBaseDir(), sourceDirs, PROPERTY_SOURCES);
+    String[] sourcePaths = getListFromProperty(properties, PROPERTY_SOURCES);
+    checkExistenceOfPaths(project.getKey(), project.getBaseDir(), sourcePaths, PROPERTY_SOURCES);
 
     // And we need to resolve patterns that may have been used in "sonar.libraries"
     List<String> libPaths = Lists.newArrayList();
@@ -415,8 +415,8 @@ public class ProjectReactorBuilder {
   }
 
   @VisibleForTesting
-  protected static void checkExistenceOfDirectories(String moduleRef, File baseDir, String[] sourceDirs, String propName) {
-    for (String path : sourceDirs) {
+  protected static void checkExistenceOfDirectories(String moduleRef, File baseDir, String[] dirPaths, String propName) {
+    for (String path : dirPaths) {
       File sourceFolder = resolvePath(baseDir, path);
       if (!sourceFolder.isDirectory()) {
         LOG.error(MessageFormat.format(INVALID_VALUE_OF_X_FOR_Y, propName, moduleRef));
@@ -427,6 +427,19 @@ public class ProjectReactorBuilder {
 
   }
 
+  @VisibleForTesting
+  protected static void checkExistenceOfPaths(String moduleRef, File baseDir, String[] paths, String propName) {
+    for (String path : paths) {
+      File sourceFolder = resolvePath(baseDir, path);
+      if (!sourceFolder.exists()) {
+        LOG.error(MessageFormat.format(INVALID_VALUE_OF_X_FOR_Y, propName, moduleRef));
+        throw new IllegalStateException("The folder '" + path + "' does not exist for '" + moduleRef +
+          "' (base directory = " + baseDir.getAbsolutePath() + ")");
+      }
+    }
+
+  }
+
   /**
    * Returns files matching specified pattern.
    */
index 0e534a334f9b0021ac605eebac759a7c27e3a131..2706e54731fe1f28c3e72dec1f07816e93ec5c1c 100644 (file)
@@ -41,6 +41,7 @@ import javax.annotation.Nullable;
 
 import java.io.File;
 import java.nio.charset.Charset;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -59,11 +60,9 @@ public class DefaultModuleFileSystem extends DefaultFileSystem implements Module
   private final Settings settings;
 
   private File buildDir;
-  private List<File> sourceDirs = Lists.newArrayList();
-  private List<File> testDirs = Lists.newArrayList();
+  private List<File> sourceDirsOrFiles = Lists.newArrayList();
+  private List<File> testDirsOrFiles = Lists.newArrayList();
   private List<File> binaryDirs = Lists.newArrayList();
-  private List<File> sourceFiles = Lists.newArrayList();
-  private List<File> testFiles = Lists.newArrayList();
   private ComponentIndexer componentIndexer;
   private boolean initialized;
 
@@ -71,19 +70,19 @@ public class DefaultModuleFileSystem extends DefaultFileSystem implements Module
    * Used by scan2 
    */
   public DefaultModuleFileSystem(ModuleInputFileCache moduleInputFileCache, ProjectDefinition def, Settings settings,
-                                 FileIndexer indexer, ModuleFileSystemInitializer initializer) {
+    FileIndexer indexer, ModuleFileSystemInitializer initializer) {
     this(moduleInputFileCache, def.getKey(), settings, indexer, initializer, null);
   }
 
   public DefaultModuleFileSystem(ModuleInputFileCache moduleInputFileCache, ProjectDefinition def, Project project,
-                                 Settings settings, FileIndexer indexer,
+    Settings settings, FileIndexer indexer,
     ModuleFileSystemInitializer initializer,
     ComponentIndexer componentIndexer) {
     this(moduleInputFileCache, project.getKey(), settings, indexer, initializer, componentIndexer);
   }
 
   private DefaultModuleFileSystem(ModuleInputFileCache moduleInputFileCache, String moduleKey, Settings settings,
-                                  FileIndexer indexer, ModuleFileSystemInitializer initializer,
+    FileIndexer indexer, ModuleFileSystemInitializer initializer,
     @Nullable ComponentIndexer componentIndexer) {
     super(moduleInputFileCache);
     this.componentIndexer = componentIndexer;
@@ -95,11 +94,9 @@ public class DefaultModuleFileSystem extends DefaultFileSystem implements Module
     }
     setWorkDir(initializer.workingDir());
     this.buildDir = initializer.buildDir();
-    this.sourceDirs = initializer.sourceDirs();
-    this.testDirs = initializer.testDirs();
+    this.sourceDirsOrFiles = initializer.sources();
+    this.testDirsOrFiles = initializer.tests();
     this.binaryDirs = initializer.binaryDirs();
-    this.sourceFiles = initializer.additionalSourceFiles();
-    this.testFiles = initializer.additionalTestFiles();
   }
 
   public boolean isInitialized() {
@@ -118,25 +115,35 @@ public class DefaultModuleFileSystem extends DefaultFileSystem implements Module
 
   @Override
   public List<File> sourceDirs() {
-    return sourceDirs;
+    return keepOnlyDirs(sourceDirsOrFiles);
+  }
+
+  public List<File> sources() {
+    return sourceDirsOrFiles;
   }
 
   @Override
   public List<File> testDirs() {
-    return testDirs;
+    return keepOnlyDirs(testDirsOrFiles);
   }
 
-  @Override
-  public List<File> binaryDirs() {
-    return binaryDirs;
+  public List<File> tests() {
+    return testDirsOrFiles;
   }
 
-  List<File> sourceFiles() {
-    return sourceFiles;
+  private List<File> keepOnlyDirs(List<File> dirsOrFiles) {
+    List<File> result = new ArrayList<File>();
+    for (File f : dirsOrFiles) {
+      if (f.isDirectory()) {
+        result.add(f);
+      }
+    }
+    return result;
   }
 
-  List<File> testFiles() {
-    return testFiles;
+  @Override
+  public List<File> binaryDirs() {
+    return binaryDirs;
   }
 
   @Override
@@ -223,9 +230,9 @@ public class DefaultModuleFileSystem extends DefaultFileSystem implements Module
     }
     setBaseDir(basedir);
     this.buildDir = buildDir;
-    this.sourceDirs = existingDirs(sourceDirs);
-    this.testDirs = existingDirs(testDirs);
-    this.binaryDirs = existingDirs(binaryDirs);
+    this.sourceDirsOrFiles = existingDirsOrFiles(sourceDirs);
+    this.testDirsOrFiles = existingDirsOrFiles(testDirs);
+    this.binaryDirs = existingDirsOrFiles(binaryDirs);
   }
 
   public void index() {
@@ -239,11 +246,11 @@ public class DefaultModuleFileSystem extends DefaultFileSystem implements Module
     }
   }
 
-  private List<File> existingDirs(List<File> dirs) {
+  private List<File> existingDirsOrFiles(List<File> dirsOrFiles) {
     ImmutableList.Builder<File> builder = ImmutableList.builder();
-    for (File dir : dirs) {
-      if (dir.exists() && dir.isDirectory()) {
-        builder.add(dir);
+    for (File dirOrFile : dirsOrFiles) {
+      if (dirOrFile.exists()) {
+        builder.add(dirOrFile);
       }
     }
     return builder.build();
index f63ce8e80d9bb69b436f605e144417cc6d4fe373..81eb9b0e4da545bdd76a75b7efd09083fca0aff2 100644 (file)
@@ -87,19 +87,8 @@ public class FileIndexer implements BatchComponent {
     executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
 
     InputFileBuilder inputFileBuilder = inputFileBuilderFactory.create(fileSystem);
-    if (!fileSystem.sourceFiles().isEmpty() || !fileSystem.testFiles().isEmpty()) {
-      // Index only provided files
-      indexFiles(inputFileBuilder, fileSystem, progress, fileSystem.sourceFiles(), InputFile.Type.MAIN);
-      indexFiles(inputFileBuilder, fileSystem, progress, fileSystem.testFiles(), InputFile.Type.TEST);
-    } else {
-      for (File mainDir : fileSystem.sourceDirs()) {
-        indexDirectory(inputFileBuilder, fileSystem, progress, mainDir, InputFile.Type.MAIN);
-      }
-      for (File testDir : fileSystem.testDirs()) {
-        indexDirectory(inputFileBuilder, fileSystem, progress, testDir, InputFile.Type.TEST);
-      }
-
-    }
+    indexFiles(fileSystem, progress, inputFileBuilder, fileSystem.sources(), InputFile.Type.MAIN);
+    indexFiles(fileSystem, progress, inputFileBuilder, fileSystem.tests(), InputFile.Type.TEST);
 
     executor.shutdown();
     try {
@@ -122,22 +111,33 @@ public class FileIndexer implements BatchComponent {
 
   }
 
+  private void indexFiles(DefaultModuleFileSystem fileSystem, Progress progress, InputFileBuilder inputFileBuilder, List<File> sources, InputFile.Type type) {
+    for (File dirOrFile : sources) {
+      if (dirOrFile.isDirectory()) {
+        indexDirectory(inputFileBuilder, fileSystem, progress, dirOrFile, type);
+      } else {
+        indexFile(inputFileBuilder, fileSystem, progress, dirOrFile, type);
+      }
+    }
+  }
+
   private void indexFiles(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fileSystem, Progress progress, List<File> sourceFiles, InputFile.Type type) {
     for (File sourceFile : sourceFiles) {
-      DeprecatedDefaultInputFile inputFile = inputFileBuilder.create(sourceFile);
-      if (inputFile != null && exclusionFilters.accept(inputFile, type)) {
-        indexFile(inputFileBuilder, fileSystem, progress, inputFile, type);
-      }
+      indexFile(inputFileBuilder, fileSystem, progress, sourceFile, type);
     }
   }
 
   private void indexDirectory(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fileSystem, Progress status, File dirToIndex, InputFile.Type type) {
     Collection<File> files = FileUtils.listFiles(dirToIndex, FILE_FILTER, DIR_FILTER);
     for (File file : files) {
-      DeprecatedDefaultInputFile inputFile = inputFileBuilder.create(file);
-      if (inputFile != null && exclusionFilters.accept(inputFile, type)) {
-        indexFile(inputFileBuilder, fileSystem, status, inputFile, type);
-      }
+      indexFile(inputFileBuilder, fileSystem, status, file, type);
+    }
+  }
+
+  private void indexFile(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fileSystem, Progress progress, File sourceFile, InputFile.Type type) {
+    DeprecatedDefaultInputFile inputFile = inputFileBuilder.create(sourceFile);
+    if (inputFile != null && exclusionFilters.accept(inputFile, type)) {
+      indexFile(inputFileBuilder, fileSystem, progress, inputFile, type);
     }
   }
 
index 5f9d1081ac9bc0c4e4a0389bba85c4f85a2afb95..fa79c8e682d9264441f2fce6ea35005eab93043c 100644 (file)
@@ -35,11 +35,9 @@ import java.util.List;
 public class ModuleFileSystemInitializer implements BatchComponent {
 
   private File baseDir, workingDir, buildDir;
-  private List<File> sourceDirs = Lists.newArrayList();
-  private List<File> testDirs = Lists.newArrayList();
+  private List<File> sourceDirsOrFiles = Lists.newArrayList();
+  private List<File> testDirsOrFiles = Lists.newArrayList();
   private List<File> binaryDirs = Lists.newArrayList();
-  private List<File> additionalSourceFiles;
-  private List<File> additionalTestFiles;
 
   public ModuleFileSystemInitializer(ProjectDefinition module, TempFolder tempUtils, PathResolver pathResolver) {
     baseDir = module.getBaseDir();
@@ -64,23 +62,21 @@ public class ModuleFileSystemInitializer implements BatchComponent {
   }
 
   private void initSources(ProjectDefinition module, PathResolver pathResolver) {
-    for (String sourcePath : module.getSourceDirs()) {
-      File dir = pathResolver.relativeFile(module.getBaseDir(), sourcePath);
-      if (dir.isDirectory() && dir.exists()) {
-        sourceDirs.add(dir);
+    for (String sourcePath : module.sources()) {
+      File dirOrFile = pathResolver.relativeFile(module.getBaseDir(), sourcePath);
+      if (dirOrFile.exists()) {
+        sourceDirsOrFiles.add(dirOrFile);
       }
     }
-    additionalSourceFiles = pathResolver.relativeFiles(module.getBaseDir(), module.getSourceFiles());
   }
 
   private void initTests(ProjectDefinition module, PathResolver pathResolver) {
-    for (String testPath : module.getTestDirs()) {
-      File dir = pathResolver.relativeFile(module.getBaseDir(), testPath);
-      if (dir.exists() && dir.isDirectory()) {
-        testDirs.add(dir);
+    for (String testPath : module.tests()) {
+      File dirOrFile = pathResolver.relativeFile(module.getBaseDir(), testPath);
+      if (dirOrFile.exists()) {
+        testDirsOrFiles.add(dirOrFile);
       }
     }
-    additionalTestFiles = pathResolver.relativeFiles(module.getBaseDir(), module.getTestFiles());
   }
 
   private void initBinaryDirs(ProjectDefinition module, PathResolver pathResolver) {
@@ -102,23 +98,15 @@ public class ModuleFileSystemInitializer implements BatchComponent {
     return buildDir;
   }
 
-  List<File> sourceDirs() {
-    return sourceDirs;
+  List<File> sources() {
+    return sourceDirsOrFiles;
   }
 
-  List<File> testDirs() {
-    return testDirs;
+  List<File> tests() {
+    return testDirsOrFiles;
   }
 
   List<File> binaryDirs() {
     return binaryDirs;
   }
-
-  List<File> additionalSourceFiles() {
-    return additionalSourceFiles;
-  }
-
-  List<File> additionalTestFiles() {
-    return additionalTestFiles;
-  }
 }
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/fs/FileSystemMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/fs/FileSystemMediumTest.java
new file mode 100644 (file)
index 0000000..aafeada
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * 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.batch.mediumtest.fs;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.commons.io.FileUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.batch.mediumtest.AnalyzerMediumTester;
+import org.sonar.batch.mediumtest.AnalyzerMediumTester.TaskResult;
+import org.sonar.batch.mediumtest.xoo.plugin.XooPlugin;
+import org.sonar.batch.mediumtest.xoo.plugin.base.Xoo;
+
+import java.io.File;
+import java.io.IOException;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class FileSystemMediumTest {
+
+  @org.junit.Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  public AnalyzerMediumTester tester = AnalyzerMediumTester.builder()
+    .registerPlugin("xoo", new XooPlugin())
+    .registerLanguage(new Xoo())
+    .addDefaultQProfile("xoo", "Sonar Way")
+    .activateRule(RuleKey.of("xoo", "OneIssuePerLine"))
+    .bootstrapProperties(ImmutableMap.of("sonar.analysis.mode", "sensor"))
+    .build();
+
+  private File baseDir;
+
+  private ImmutableMap.Builder<String, String> builder;
+
+  @Before
+  public void prepare() throws IOException {
+    tester.start();
+
+    baseDir = temp.newFolder();
+
+    builder = 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");
+  }
+
+  @After
+  public void stop() {
+    tester.stop();
+  }
+
+  @Test
+  public void scanProjectWithSourceDir() throws IOException {
+    File srcDir = new File(baseDir, "src");
+    srcDir.mkdir();
+
+    File xooFile = new File(srcDir, "sample.xoo");
+    FileUtils.write(xooFile, "Sample xoo\ncontent");
+
+    TaskResult result = tester.newTask()
+      .properties(builder
+        .put("sonar.sources", "src")
+        .build())
+      .start();
+
+    assertThat(result.inputFiles()).hasSize(1);
+    assertThat(result.inputFiles().get(0).type()).isEqualTo(InputFile.Type.MAIN);
+  }
+
+  @Test
+  public void scanProjectWithTestDir() throws IOException {
+    File test = new File(baseDir, "test");
+    test.mkdir();
+
+    File xooFile = new File(test, "sampleTest.xoo");
+    FileUtils.write(xooFile, "Sample test xoo\ncontent");
+
+    TaskResult result = tester.newTask()
+      .properties(builder
+        .put("sonar.sources", "")
+        .put("sonar.tests", "test")
+        .build())
+      .start();
+
+    assertThat(result.inputFiles()).hasSize(1);
+    assertThat(result.inputFiles().get(0).type()).isEqualTo(InputFile.Type.TEST);
+  }
+
+  @Test
+  public void scanProjectWithMixedSourcesAndTests() throws IOException {
+    File srcDir = new File(baseDir, "src");
+    srcDir.mkdir();
+
+    File xooFile = new File(srcDir, "sample.xoo");
+    FileUtils.write(xooFile, "Sample xoo\ncontent");
+
+    File xooFile2 = new File(baseDir, "another.xoo");
+    FileUtils.write(xooFile2, "Sample xoo 2\ncontent");
+
+    File testDir = new File(baseDir, "test");
+    testDir.mkdir();
+
+    File xooTestFile = new File(baseDir, "sampleTest2.xoo");
+    FileUtils.write(xooTestFile, "Sample test xoo\ncontent");
+
+    File xooTestFile2 = new File(testDir, "sampleTest.xoo");
+    FileUtils.write(xooTestFile2, "Sample test xoo 2\ncontent");
+
+    TaskResult result = tester.newTask()
+      .properties(builder
+        .put("sonar.sources", "src,another.xoo")
+        .put("sonar.tests", "test,sampleTest2.xoo")
+        .build())
+      .start();
+
+    assertThat(result.inputFiles()).hasSize(4);
+  }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java
new file mode 100644 (file)
index 0000000..75663d7
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.batch.mediumtest.issues;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.commons.io.FileUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.analyzer.issue.AnalyzerIssue;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.batch.mediumtest.AnalyzerMediumTester;
+import org.sonar.batch.mediumtest.AnalyzerMediumTester.TaskResult;
+import org.sonar.batch.mediumtest.xoo.plugin.XooPlugin;
+import org.sonar.batch.mediumtest.xoo.plugin.base.Xoo;
+
+import java.io.File;
+import java.io.IOException;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class IssuesMediumTest {
+
+  @org.junit.Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  public AnalyzerMediumTester tester = AnalyzerMediumTester.builder()
+    .registerPlugin("xoo", new XooPlugin())
+    .registerLanguage(new Xoo())
+    .addDefaultQProfile("xoo", "Sonar Way")
+    .activateRule(RuleKey.of("xoo", "OneIssuePerLine"))
+    .bootstrapProperties(ImmutableMap.of("sonar.analysis.mode", "sensor"))
+    .build();
+
+  @Before
+  public void prepare() {
+    tester.start();
+  }
+
+  @After
+  public void stop() {
+    tester.stop();
+  }
+
+  @Test
+  public void scanSampleProject() throws Exception {
+    File projectDir = new File(IssuesMediumTest.class.getResource("/mediumtest/xoo/sample").toURI());
+
+    TaskResult result = tester
+      .newScanTask(new File(projectDir, "sonar-project.properties"))
+      .start();
+
+    assertThat(result.issues()).hasSize(24);
+  }
+
+  @Test
+  public void testIssueExclusion() throws Exception {
+    File projectDir = new File(IssuesMediumTest.class.getResource("/mediumtest/xoo/sample").toURI());
+
+    TaskResult result = tester
+      .newScanTask(new File(projectDir, "sonar-project.properties"))
+      .property("sonar.issue.ignore.allfile", "1")
+      .property("sonar.issue.ignore.allfile.1.fileRegexp", "object")
+      .start();
+
+    assertThat(result.issues()).hasSize(19);
+  }
+
+  @Test
+  public void scanTempProject() throws IOException {
+
+    File baseDir = temp.newFolder();
+    File srcDir = new File(baseDir, "src");
+    srcDir.mkdir();
+
+    File xooFile = new File(srcDir, "sample.xoo");
+    File xooMeasureFile = new File(srcDir, "sample.xoo.measures");
+    FileUtils.write(xooFile, "Sample xoo\ncontent");
+    FileUtils.write(xooMeasureFile, "lines:20");
+
+    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();
+
+    assertThat(result.issues()).hasSize(20);
+
+    boolean foundIssueAtLine1 = false;
+    for (AnalyzerIssue issue : result.issues()) {
+      if (issue.line() == 1) {
+        foundIssueAtLine1 = true;
+        assertThat(issue.inputFile()).isEqualTo(new DefaultInputFile("src/sample.xoo"));
+        assertThat(issue.message()).isEqualTo("This issue is generated on each line");
+        assertThat(issue.effortToFix()).isNull();
+      }
+    }
+    assertThat(foundIssueAtLine1).isTrue();
+  }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java
new file mode 100644 (file)
index 0000000..017f530
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * 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.batch.mediumtest.measures;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.commons.io.FileUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.analyzer.measure.internal.DefaultAnalyzerMeasureBuilder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.batch.mediumtest.AnalyzerMediumTester;
+import org.sonar.batch.mediumtest.AnalyzerMediumTester.TaskResult;
+import org.sonar.batch.mediumtest.xoo.plugin.XooPlugin;
+import org.sonar.batch.mediumtest.xoo.plugin.base.Xoo;
+
+import java.io.File;
+import java.io.IOException;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class MeasuresMediumTest {
+
+  @org.junit.Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  public AnalyzerMediumTester tester = AnalyzerMediumTester.builder()
+    .registerPlugin("xoo", new XooPlugin())
+    .registerLanguage(new Xoo())
+    .addDefaultQProfile("xoo", "Sonar Way")
+    .bootstrapProperties(ImmutableMap.of("sonar.analysis.mode", "sensor"))
+    .build();
+
+  @Before
+  public void prepare() {
+    tester.start();
+  }
+
+  @After
+  public void stop() {
+    tester.stop();
+  }
+
+  @Test
+  public void computeMeasuresOnSampleProject() throws Exception {
+    File projectDir = new File(MeasuresMediumTest.class.getResource("/mediumtest/xoo/sample").toURI());
+
+    TaskResult result = tester
+      .newScanTask(new File(projectDir, "sonar-project.properties"))
+      .start();
+
+    assertThat(result.measures()).hasSize(19);
+  }
+
+  @Test
+  public void computeMeasuresOnTempProject() throws IOException {
+
+    File baseDir = temp.newFolder();
+    File srcDir = new File(baseDir, "src");
+    srcDir.mkdir();
+
+    File xooFile = new File(srcDir, "sample.xoo");
+    File xooMeasureFile = new File(srcDir, "sample.xoo.measures");
+    FileUtils.write(xooFile, "Sample xoo\ncontent");
+    FileUtils.write(xooMeasureFile, "lines:20");
+
+    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();
+
+    assertThat(result.measures()).hasSize(1);
+
+    assertThat(result.measures()).contains(new DefaultAnalyzerMeasureBuilder<Integer>()
+      .forMetric(CoreMetrics.LINES)
+      .onFile(new DefaultInputFile("src/sample.xoo"))
+      .withValue(20)
+      .build());
+
+  }
+
+  @Test
+  public void testDistributionMeasure() throws IOException {
+
+    File baseDir = temp.newFolder();
+    File srcDir = new File(baseDir, "src");
+    srcDir.mkdir();
+
+    File xooFile = new File(srcDir, "sample.xoo");
+    File xooMeasureFile = new File(srcDir, "sample.xoo.measures");
+    File xooScmFile = new File(srcDir, "sample.xoo.scm");
+    FileUtils.write(xooFile, "Sample xoo\ncontent");
+    FileUtils.write(xooMeasureFile, "lines:5");
+    FileUtils.write(xooScmFile,
+      // revision,author,dateTime
+      "1,julien,2013-01-04\n" +
+        "1,julien,2013-01-04\n" +
+        "2,julien,2013-02-03\n" +
+        "2,julien,2013-02-03\n" +
+        "3,simon,2013-03-04\n"
+      );
+
+    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();
+
+    assertThat(result.measures()).hasSize(4);
+
+    assertThat(result.measures()).contains(new DefaultAnalyzerMeasureBuilder<Integer>()
+      .forMetric(CoreMetrics.LINES)
+      .onFile(new DefaultInputFile("src/sample.xoo"))
+      .withValue(5)
+      .build());
+
+    assertThat(result.measures()).contains(new DefaultAnalyzerMeasureBuilder<String>()
+      .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
+      .onFile(new DefaultInputFile("src/sample.xoo"))
+      .withValue("1=julien;2=julien;3=julien;4=julien;5=simon")
+      .build());
+  }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/XooMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/XooMediumTest.java
deleted file mode 100644 (file)
index 14a22cb..0000000
+++ /dev/null
@@ -1,186 +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.batch.mediumtest.xoo;
-
-import com.google.common.collect.ImmutableMap;
-import org.apache.commons.io.FileUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.analyzer.issue.AnalyzerIssue;
-import org.sonar.api.batch.analyzer.measure.internal.DefaultAnalyzerMeasureBuilder;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.batch.mediumtest.AnalyzerMediumTester;
-import org.sonar.batch.mediumtest.AnalyzerMediumTester.TaskResult;
-import org.sonar.batch.mediumtest.xoo.plugin.XooPlugin;
-import org.sonar.batch.mediumtest.xoo.plugin.base.Xoo;
-
-import java.io.File;
-import java.io.IOException;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class XooMediumTest {
-
-  @org.junit.Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  public AnalyzerMediumTester tester = AnalyzerMediumTester.builder()
-    // .registerPlugin("xoo", new File("target/sonar-xoo-plugin-2.0-SNAPSHOT.jar"))
-    .registerPlugin("xoo", new XooPlugin())
-    .registerLanguage(new Xoo())
-    .addDefaultQProfile("xoo", "Sonar Way")
-    .activateRule(RuleKey.of("xoo", "OneIssuePerLine"))
-    .bootstrapProperties(ImmutableMap.of("sonar.analysis.mode", "sensor"))
-    .build();
-
-  @Before
-  public void prepare() {
-    tester.start();
-  }
-
-  @After
-  public void stop() {
-    tester.stop();
-  }
-
-  @Test
-  public void mediumTestOfSampleProject() throws Exception {
-    File projectDir = new File(XooMediumTest.class.getResource("/mediumtest/xoo/sample").toURI());
-
-    TaskResult result = tester
-      .newScanTask(new File(projectDir, "sonar-project.properties"))
-      .start();
-
-    assertThat(result.measures()).hasSize(19);
-    assertThat(result.issues()).hasSize(24);
-  }
-
-  @Test
-  public void testIssueExclusion() throws Exception {
-    File projectDir = new File(XooMediumTest.class.getResource("/mediumtest/xoo/sample").toURI());
-
-    TaskResult result = tester
-      .newScanTask(new File(projectDir, "sonar-project.properties"))
-      .property("sonar.issue.ignore.allfile", "1")
-      .property("sonar.issue.ignore.allfile.1.fileRegexp", "object")
-      .start();
-
-    assertThat(result.measures()).hasSize(19);
-    assertThat(result.issues()).hasSize(19);
-  }
-
-  @Test
-  public void testMeasuresAndIssues() throws IOException {
-
-    File baseDir = temp.newFolder();
-    File srcDir = new File(baseDir, "src");
-    srcDir.mkdir();
-
-    File xooFile = new File(srcDir, "sample.xoo");
-    File xooMeasureFile = new File(srcDir, "sample.xoo.measures");
-    FileUtils.write(xooFile, "Sample xoo\ncontent");
-    FileUtils.write(xooMeasureFile, "lines:20");
-
-    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();
-
-    assertThat(result.measures()).hasSize(1);
-    assertThat(result.issues()).hasSize(20);
-
-    assertThat(result.measures()).contains(new DefaultAnalyzerMeasureBuilder<Integer>()
-      .forMetric(CoreMetrics.LINES)
-      .onFile(new DefaultInputFile("src/sample.xoo"))
-      .withValue(20)
-      .build());
-
-    boolean foundIssueAtLine1 = false;
-    for (AnalyzerIssue issue : result.issues()) {
-      if (issue.line() == 1) {
-        foundIssueAtLine1 = true;
-        assertThat(issue.inputFile()).isEqualTo(new DefaultInputFile("src/sample.xoo"));
-        assertThat(issue.message()).isEqualTo("This issue is generated on each line");
-        assertThat(issue.effortToFix()).isNull();
-      }
-    }
-    assertThat(foundIssueAtLine1).isTrue();
-  }
-
-  @Test
-  public void testScmActivityAnalyzer() throws IOException {
-
-    File baseDir = temp.newFolder();
-    File srcDir = new File(baseDir, "src");
-    srcDir.mkdir();
-
-    File xooFile = new File(srcDir, "sample.xoo");
-    File xooMeasureFile = new File(srcDir, "sample.xoo.measures");
-    File xooScmFile = new File(srcDir, "sample.xoo.scm");
-    FileUtils.write(xooFile, "Sample xoo\ncontent");
-    FileUtils.write(xooMeasureFile, "lines:5");
-    FileUtils.write(xooScmFile,
-      // revision,author,dateTime
-      "1,julien,2013-01-04\n" +
-        "1,julien,2013-01-04\n" +
-        "2,julien,2013-02-03\n" +
-        "2,julien,2013-02-03\n" +
-        "3,simon,2013-03-04\n"
-      );
-
-    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();
-
-    assertThat(result.measures()).hasSize(4);
-
-    assertThat(result.measures()).contains(new DefaultAnalyzerMeasureBuilder<Integer>()
-      .forMetric(CoreMetrics.LINES)
-      .onFile(new DefaultInputFile("src/sample.xoo"))
-      .withValue(5)
-      .build());
-
-    assertThat(result.measures()).contains(new DefaultAnalyzerMeasureBuilder<String>()
-      .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
-      .onFile(new DefaultInputFile("src/sample.xoo"))
-      .withValue("1=julien;2=julien;3=julien;4=julien;5=simon")
-      .build());
-  }
-
-}
index 0de8ac80c56811e08a0d8ef5d102d0efee54b187..4d87aed7cd33be2de90618599747c85fe7d0f920 100644 (file)
@@ -111,10 +111,14 @@ public class DefaultModuleFileSystemTest {
     when(initializer.buildDir()).thenReturn(buildDir);
     when(initializer.workingDir()).thenReturn(workingDir);
     when(initializer.binaryDirs()).thenReturn(Arrays.asList(new File(basedir, "target/classes")));
-    when(initializer.sourceDirs()).thenReturn(Arrays.asList(new File(basedir, "src/main/java"), new File(basedir, "src/main/groovy")));
-    when(initializer.testDirs()).thenReturn(Arrays.asList(new File(basedir, "src/test/java")));
-    when(initializer.additionalSourceFiles()).thenReturn(Arrays.asList(additionalFile));
-    when(initializer.additionalTestFiles()).thenReturn(Arrays.asList(additionalTest));
+    File javaSrc = new File(basedir, "src/main/java");
+    javaSrc.mkdirs();
+    File groovySrc = new File(basedir, "src/main/groovy");
+    groovySrc.mkdirs();
+    when(initializer.sources()).thenReturn(Arrays.asList(javaSrc, groovySrc, additionalFile));
+    File javaTest = new File(basedir, "src/test/java");
+    javaTest.mkdirs();
+    when(initializer.tests()).thenReturn(Arrays.asList(javaTest, additionalTest));
 
     DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
       new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
@@ -125,8 +129,6 @@ public class DefaultModuleFileSystemTest {
     assertThat(fs.sourceDirs()).hasSize(2);
     assertThat(fs.testDirs()).hasSize(1);
     assertThat(fs.binaryDirs()).hasSize(1);
-    assertThat(fs.sourceFiles()).containsOnly(additionalFile);
-    assertThat(fs.testFiles()).containsOnly(additionalTest);
   }
 
   @Test
@@ -134,7 +136,7 @@ public class DefaultModuleFileSystemTest {
     File basedir = temp.newFolder();
     when(initializer.baseDir()).thenReturn(basedir);
     when(initializer.workingDir()).thenReturn(basedir);
-    when(initializer.sourceDirs()).thenReturn(Arrays.asList(new File(basedir, "src/main/java")));
+    when(initializer.sources()).thenReturn(Arrays.asList(new File(basedir, "src/main/java")));
 
     DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
       new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
index 21e6203d565437aa28cca06983157c9ece60d9b9..78868ef607c1c863e14a74993bdf9f541e9b741e 100644 (file)
@@ -51,8 +51,8 @@ public class ModuleFileSystemInitializerTest {
 
     assertThat(initializer.baseDir().getCanonicalPath()).isEqualTo(baseDir.getCanonicalPath());
     assertThat(initializer.workingDir().getCanonicalPath()).isEqualTo(workDir.getCanonicalPath());
-    assertThat(initializer.sourceDirs()).isEmpty();
-    assertThat(initializer.testDirs()).isEmpty();
+    assertThat(initializer.sources()).isEmpty();
+    assertThat(initializer.tests()).isEmpty();
   }
 
   @Test
@@ -77,10 +77,10 @@ public class ModuleFileSystemInitializerTest {
 
     assertThat(initializer.baseDir().getCanonicalPath()).isEqualTo(baseDir.getCanonicalPath());
     assertThat(initializer.buildDir().getCanonicalPath()).isEqualTo(buildDir.getCanonicalPath());
-    assertThat(initializer.sourceDirs()).hasSize(1);
-    assertThat(path(initializer.sourceDirs().get(0))).endsWith("src/main/java");
-    assertThat(initializer.testDirs()).hasSize(1);
-    assertThat(path(initializer.testDirs().get(0))).endsWith("src/test/java");
+    assertThat(initializer.sources()).hasSize(1);
+    assertThat(path(initializer.sources().get(0))).endsWith("src/main/java");
+    assertThat(initializer.tests()).hasSize(1);
+    assertThat(path(initializer.tests().get(0))).endsWith("src/test/java");
     assertThat(initializer.binaryDirs()).hasSize(1);
     assertThat(path(initializer.binaryDirs().get(0))).endsWith("target/classes");
   }
index 62c4da3d65389b160da7538a1bf39b3b164af171..b228e383421876ad11c504199ecc84270e791ef0 100644 (file)
@@ -39,9 +39,28 @@ import java.util.Properties;
  */
 public class ProjectDefinition {
 
-  public static final String SOURCE_DIRS_PROPERTY = "sonar.sources";
+  public static final String SOURCES_PROPERTY = "sonar.sources";
+  /**
+   * @deprecated since 4.5 use {@link #SOURCES_PROPERTY}
+   */
+  @Deprecated
+  public static final String SOURCE_DIRS_PROPERTY = SOURCES_PROPERTY;
+  /**
+   * @deprecated since 4.5 use {@link #SOURCES_PROPERTY}
+   */
+  @Deprecated
   public static final String SOURCE_FILES_PROPERTY = "sonar.sourceFiles";
-  public static final String TEST_DIRS_PROPERTY = "sonar.tests";
+
+  public static final String TESTS_PROPERTY = "sonar.tests";
+  /**
+   * @deprecated since 4.5 use {@link #TESTS_PROPERTY}
+   */
+  @Deprecated
+  public static final String TEST_DIRS_PROPERTY = TESTS_PROPERTY;
+  /**
+   * @deprecated since 4.5 use {@link #TESTS_PROPERTY}
+   */
+  @Deprecated
   public static final String TEST_FILES_PROPERTY = "sonar.testFiles";
   public static final String BINARIES_PROPERTY = "sonar.binaries";
   public static final String LIBRARIES_PROPERTY = "sonar.libraries";
@@ -167,39 +186,94 @@ public class ProjectDefinition {
     properties.put(key, newValue);
   }
 
-  public List<String> getSourceDirs() {
-    String sources = properties.getProperty(SOURCE_DIRS_PROPERTY, "");
+  /**
+   * @return Source files and folders.
+   */
+  public List<String> sources() {
+    String sources = properties.getProperty(SOURCES_PROPERTY, "");
     return trim(StringUtils.split(sources, SEPARATOR));
   }
 
   /**
-   * @param paths paths to directory with main sources.
+   * @deprecated since 4.5 use {@link #sources()}
+   */
+  @Deprecated
+  public List<String> getSourceDirs() {
+    return sources();
+  }
+
+  /**
+   * @param paths paths to file or directory with main sources.
    *              They can be absolute or relative to project base directory.
    */
-  public ProjectDefinition addSourceDirs(String... paths) {
+  public ProjectDefinition addSources(String... paths) {
     for (String path : paths) {
-      appendProperty(SOURCE_DIRS_PROPERTY, path);
+      appendProperty(SOURCES_PROPERTY, path);
     }
     return this;
   }
 
-  public ProjectDefinition addSourceDirs(File... dirs) {
-    for (File dir : dirs) {
-      addSourceDirs(dir.getAbsolutePath());
+  /**
+   * @deprecated since 4.5 use {@link #addSources(String...)}
+   */
+  @Deprecated
+  public ProjectDefinition addSourceDirs(String... paths) {
+    return addSources(paths);
+  }
+
+  public ProjectDefinition addSources(File... fileOrDirs) {
+    for (File fileOrDir : fileOrDirs) {
+      addSources(fileOrDir.getAbsolutePath());
     }
     return this;
   }
 
-  public ProjectDefinition resetSourceDirs() {
-    properties.remove(SOURCE_DIRS_PROPERTY);
+  /**
+   * @deprecated since 4.5 use {@link #addSources(File...)}
+   */
+  @Deprecated
+  public ProjectDefinition addSourceDirs(File... dirs) {
+    return addSources(dirs);
+  }
+
+  public ProjectDefinition resetSources() {
+    properties.remove(SOURCES_PROPERTY);
     return this;
   }
 
+  /**
+   * @deprecated since 4.5 use {@link #resetSources()}
+   */
+  @Deprecated
+  public ProjectDefinition resetSourceDirs() {
+    return resetSources();
+  }
+
+  public ProjectDefinition setSources(String... paths) {
+    resetSources();
+    return addSources(paths);
+  }
+
+  /**
+   * @deprecated since 4.5 use {@link #setSources(String...)}
+   */
+  @Deprecated
   public ProjectDefinition setSourceDirs(String... paths) {
-    resetSourceDirs();
-    return addSourceDirs(paths);
+    return setSources(paths);
   }
 
+  public ProjectDefinition setSources(File... filesOrDirs) {
+    resetSources();
+    for (File fileOrDir : filesOrDirs) {
+      addSources(fileOrDir.getAbsolutePath());
+    }
+    return this;
+  }
+
+  /**
+   * @deprecated since 4.5 use {@link #setSources(File...)}
+   */
+  @Deprecated
   public ProjectDefinition setSourceDirs(File... dirs) {
     resetSourceDirs();
     for (File dir : dirs) {
@@ -209,96 +283,140 @@ public class ProjectDefinition {
   }
 
   /**
-   * Adding source files is possible only if no source directories have been set.
-   * Absolute path or relative path from project base dir.
+   * @deprecated since 4.5 use {@link #addSources(File...)}
    */
+  @Deprecated
   public ProjectDefinition addSourceFiles(String... paths) {
-    for (String path : paths) {
-      appendProperty(SOURCE_FILES_PROPERTY, path);
-    }
-    return this;
+    return addSources(paths);
   }
 
   /**
-   * Adding source files is possible only if no source directories have been set.
+   * @deprecated since 4.5 use {@link #addSources(File...)}
    */
+  @Deprecated
   public ProjectDefinition addSourceFiles(File... files) {
-    for (File file : files) {
-      addSourceFiles(file.getAbsolutePath());
-    }
-    return this;
+    return addSources(files);
   }
 
+  /**
+   * @deprecated since 4.5 use {@link #sources()}
+   */
+  @Deprecated
   public List<String> getSourceFiles() {
-    String sources = properties.getProperty(SOURCE_FILES_PROPERTY, "");
+    return sources();
+  }
+
+  public List<String> tests() {
+    String sources = properties.getProperty(TESTS_PROPERTY, "");
     return trim(StringUtils.split(sources, SEPARATOR));
   }
 
+  /**
+   * @deprecated since 4.5 use {@link #tests()}
+   */
+  @Deprecated
   public List<String> getTestDirs() {
-    String sources = properties.getProperty(TEST_DIRS_PROPERTY, "");
-    return trim(StringUtils.split(sources, SEPARATOR));
+    return tests();
   }
 
   /**
-   * @param paths path to directory with test sources.
+   * @param paths path to files or directories with test sources.
    *              It can be absolute or relative to project directory.
    */
-  public ProjectDefinition addTestDirs(String... paths) {
+  public ProjectDefinition addTests(String... paths) {
     for (String path : paths) {
-      appendProperty(TEST_DIRS_PROPERTY, path);
+      appendProperty(TESTS_PROPERTY, path);
     }
     return this;
   }
 
-  public ProjectDefinition addTestDirs(File... dirs) {
-    for (File dir : dirs) {
-      addTestDirs(dir.getAbsolutePath());
+  /**
+   * @deprecated since 4.5 use {@link #addTests(String...)}
+   */
+  @Deprecated
+  public ProjectDefinition addTestDirs(String... paths) {
+    return addTests(paths);
+  }
+
+  public ProjectDefinition addTests(File... fileOrDirs) {
+    for (File fileOrDir : fileOrDirs) {
+      addTests(fileOrDir.getAbsolutePath());
     }
     return this;
   }
 
+  /**
+   * @deprecated since 4.5 use {@link #addTests(File...)}
+   */
+  @Deprecated
+  public ProjectDefinition addTestDirs(File... dirs) {
+    return addTests(dirs);
+  }
+
+  public ProjectDefinition setTests(String... paths) {
+    resetTests();
+    return addTests(paths);
+  }
+
+  /**
+   * @deprecated since 4.5 use {@link #setTests(String...)}
+   */
+  @Deprecated
   public ProjectDefinition setTestDirs(String... paths) {
-    resetTestDirs();
-    return addTestDirs(paths);
+    return setTests(paths);
   }
 
-  public ProjectDefinition setTestDirs(File... dirs) {
-    resetTestDirs();
-    for (File dir : dirs) {
-      addTestDirs(dir.getAbsolutePath());
+  public ProjectDefinition setTests(File... fileOrDirs) {
+    resetTests();
+    for (File dir : fileOrDirs) {
+      addTests(dir.getAbsolutePath());
     }
     return this;
   }
 
-  public ProjectDefinition resetTestDirs() {
-    properties.remove(TEST_DIRS_PROPERTY);
+  /**
+   * @deprecated since 4.5 use {@link #setTests(File...)}
+   */
+  @Deprecated
+  public ProjectDefinition setTestDirs(File... dirs) {
+    return setTests(dirs);
+  }
+
+  public ProjectDefinition resetTests() {
+    properties.remove(TESTS_PROPERTY);
     return this;
   }
 
   /**
-   * Adding source files is possible only if no source directories have been set.
-   * Absolute path or relative path from project base dir.
+   * @deprecated since 4.5 use {@link #resetTests()}
+   */
+  @Deprecated
+  public ProjectDefinition resetTestDirs() {
+    return resetTests();
+  }
+
+  /**
+   * @deprecated since 4.5 use {@link #addTests(String...)}
    */
+  @Deprecated
   public ProjectDefinition addTestFiles(String... paths) {
-    for (String path : paths) {
-      appendProperty(TEST_FILES_PROPERTY, path);
-    }
-    return this;
+    return addTests(paths);
   }
 
   /**
-   * Adding source files is possible only if no source directories have been set.
+   * @deprecated since 4.5 use {@link #addTests(File...)}
    */
+  @Deprecated
   public ProjectDefinition addTestFiles(File... files) {
-    for (File file : files) {
-      addTestFiles(file.getAbsolutePath());
-    }
-    return this;
+    return addTests(files);
   }
 
+  /**
+   * @deprecated since 4.5 use {@link #tests()}
+   */
+  @Deprecated
   public List<String> getTestFiles() {
-    String sources = properties.getProperty(TEST_FILES_PROPERTY, "");
-    return trim(StringUtils.split(sources, SEPARATOR));
+    return tests();
   }
 
   public List<String> getBinaries() {