Browse Source

SONAR-6068 Improve performance of FileSystem query operation

tags/5.1-RC1
Julien HENRY 9 years ago
parent
commit
9fb2ca6c4d
51 changed files with 860 additions and 224 deletions
  1. 9
    2
      plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdSensorTest.java
  2. 2
    0
      plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java
  3. 73
    0
      plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/RandomAccessSensor.java
  4. 1
    1
      plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java
  5. 1
    1
      plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/CoveragePerTestSensorTest.java
  6. 1
    1
      plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/DependencySensorTest.java
  7. 1
    1
      plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/MeasureSensorTest.java
  8. 1
    1
      plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SymbolReferencesSensorTest.java
  9. 1
    1
      plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java
  10. 1
    1
      plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/TestCaseSensorTest.java
  11. 1
    1
      plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/XooTokenizerSensorTest.java
  12. 11
    4
      plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java
  13. 1
    1
      plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/scm/XooBlameCommandTest.java
  14. 18
    0
      sonar-batch/pom.xml
  15. 0
    10
      sonar-batch/src/main/java/org/sonar/batch/maven/MavenProjectConverter.java
  16. 5
    5
      sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicates.java
  17. 1
    25
      sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java
  18. 4
    5
      sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleInputFileCache.java
  19. 1
    1
      sonar-batch/src/test/java/org/sonar/batch/debt/SqaleRatingDecoratorTest.java
  20. 5
    4
      sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java
  21. 49
    0
      sonar-batch/src/test/java/org/sonar/batch/mediumtest/Benchmark.java
  22. 136
    0
      sonar-batch/src/test/java/org/sonar/batch/mediumtest/fs/RandomFsAccessMediumTest.java
  23. 15
    2
      sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java
  24. 12
    5
      sonar-batch/src/test/java/org/sonar/batch/rule/QProfileVerifierTest.java
  25. 13
    3
      sonar-batch/src/test/java/org/sonar/batch/scan/LanguageVerifierTest.java
  26. 2
    1
      sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java
  27. 9
    35
      sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java
  28. 5
    4
      sonar-batch/src/test/java/org/sonar/batch/scan/report/JSONReportTest.java
  29. 7
    4
      sonar-batch/src/test/java/org/sonar/batch/sensor/AnalyzerOptimizerTest.java
  30. 6
    2
      sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorContextTest.java
  31. 6
    2
      sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java
  32. 60
    0
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AbstractFilePredicate.java
  33. 25
    1
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java
  34. 13
    0
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java
  35. 26
    3
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbsolutePathPredicate.java
  36. 56
    4
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AndPredicate.java
  37. 13
    12
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFilePredicates.java
  38. 28
    46
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java
  39. 15
    1
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FalsePredicate.java
  40. 3
    2
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/LanguagePredicate.java
  41. 3
    1
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/NotPredicate.java
  42. 28
    7
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OrPredicate.java
  43. 3
    2
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPatternPredicate.java
  44. 17
    2
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathPredicate.java
  45. 3
    2
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/StatusPredicate.java
  46. 13
    1
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TruePredicate.java
  47. 3
    3
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TypePredicate.java
  48. 75
    0
      sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/AndPredicateTest.java
  49. 2
    1
      sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java
  50. 11
    13
      sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java
  51. 65
    0
      sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/OrPredicateTest.java

+ 9
- 2
plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdSensorTest.java View File

@@ -20,7 +20,9 @@
package org.sonar.plugins.cpd;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.Settings;
@@ -28,24 +30,29 @@ import org.sonar.api.resources.Java;
import org.sonar.batch.duplication.BlockCache;
import org.sonar.plugins.cpd.index.IndexFactory;

import java.io.IOException;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;

public class CpdSensorTest {

@Rule
public TemporaryFolder temp = new TemporaryFolder();

JavaCpdEngine sonarEngine;
DefaultCpdEngine sonarBridgeEngine;
CpdSensor sensor;
Settings settings;

@Before
public void setUp() {
public void setUp() throws IOException {
IndexFactory indexFactory = mock(IndexFactory.class);
sonarEngine = new JavaCpdEngine(indexFactory, null, null);
sonarBridgeEngine = new DefaultCpdEngine(indexFactory, new CpdMappings(), null, null, mock(BlockCache.class));
settings = new Settings(new PropertyDefinitions(CpdPlugin.class));

DefaultFileSystem fs = new DefaultFileSystem();
DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder());
sensor = new CpdSensor(sonarEngine, sonarBridgeEngine, settings, fs);
}


+ 2
- 0
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java View File

@@ -31,6 +31,7 @@ import org.sonar.xoo.rule.ChecksSensor;
import org.sonar.xoo.rule.CreateIssueByInternalKeySensor;
import org.sonar.xoo.rule.OneIssueOnDirPerFileSensor;
import org.sonar.xoo.rule.OneIssuePerLineSensor;
import org.sonar.xoo.rule.RandomAccessSensor;
import org.sonar.xoo.rule.XooFakeExporter;
import org.sonar.xoo.rule.XooFakeImporter;
import org.sonar.xoo.rule.XooFakeImporterWithMessages;
@@ -74,6 +75,7 @@ public class XooPlugin extends SonarPlugin {
CoveragePerTestSensor.class,
DependencySensor.class,
ChecksSensor.class,
RandomAccessSensor.class,

OneIssuePerLineSensor.class,
OneIssueOnDirPerFileSensor.class,

+ 73
- 0
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/RandomAccessSensor.java View File

@@ -0,0 +1,73 @@
/*
* 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.xoo.rule;

import org.apache.commons.io.FileUtils;
import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputFile.Type;
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.rule.RuleKey;
import org.sonar.xoo.Xoo;

import java.io.File;
import java.io.IOException;

public class RandomAccessSensor implements Sensor {

private static final String SONAR_XOO_RANDOM_ACCESS_ISSUE_PATHS = "sonar.xoo.randomAccessIssue.paths";
public static final String RULE_KEY = "RandomAccessIssue";

@Override
public void describe(SensorDescriptor descriptor) {
descriptor
.name("One Issue Per File with Random Access")
.onlyOnLanguages(Xoo.KEY)
.createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY)
.requireProperty(SONAR_XOO_RANDOM_ACCESS_ISSUE_PATHS);
}

@Override
public void execute(SensorContext context) {
File f = new File(context.settings().getString(SONAR_XOO_RANDOM_ACCESS_ISSUE_PATHS));
FileSystem fs = context.fileSystem();
FilePredicates p = fs.predicates();
try {
for (String path : FileUtils.readLines(f)) {
createIssues(fs.inputFile(p.and(p.hasPath(path), p.hasType(Type.MAIN), p.hasLanguage(Xoo.KEY))), context);
}
} catch (IOException e) {
throw new IllegalStateException(e);
}
}

private void createIssues(InputFile file, SensorContext context) {
RuleKey ruleKey = RuleKey.of(XooRulesDefinition.XOO_REPOSITORY, RULE_KEY);
context.newIssue()
.ruleKey(ruleKey)
.onFile(file)
.atLine(1)
.message("This issue is generated on each file")
.save();
}
}

+ 1
- 1
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java View File

@@ -27,6 +27,6 @@ public class XooPluginTest {

@Test
public void provide_extensions() {
assertThat(new XooPlugin().getExtensions()).hasSize(19);
assertThat(new XooPlugin().getExtensions()).hasSize(20);
}
}

+ 1
- 1
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/CoveragePerTestSensorTest.java View File

@@ -57,7 +57,7 @@ public class CoveragePerTestSensorTest {
public void prepare() throws IOException {
baseDir = temp.newFolder();
sensor = new CoveragePerTestSensor();
fileSystem = new DefaultFileSystem();
fileSystem = new DefaultFileSystem(baseDir);
when(context.fileSystem()).thenReturn(fileSystem);
}


+ 1
- 1
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/DependencySensorTest.java View File

@@ -56,7 +56,7 @@ public class DependencySensorTest {
public void prepare() throws IOException {
baseDir = temp.newFolder();
sensor = new DependencySensor();
fileSystem = new DefaultFileSystem();
fileSystem = new DefaultFileSystem(baseDir);
when(context.fileSystem()).thenReturn(fileSystem);
}


+ 1
- 1
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/MeasureSensorTest.java View File

@@ -65,7 +65,7 @@ public class MeasureSensorTest {
baseDir = temp.newFolder();
metricFinder = mock(MetricFinder.class);
sensor = new MeasureSensor(metricFinder);
fileSystem = new DefaultFileSystem();
fileSystem = new DefaultFileSystem(baseDir);
when(context.fileSystem()).thenReturn(fileSystem);
storage = mock(SensorStorage.class);
when(context.newMeasure()).then(new Answer<DefaultMeasure>() {

+ 1
- 1
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SymbolReferencesSensorTest.java View File

@@ -52,7 +52,7 @@ public class SymbolReferencesSensorTest {
public void prepare() throws IOException {
baseDir = temp.newFolder();
sensor = new SymbolReferencesSensor();
fileSystem = new DefaultFileSystem();
fileSystem = new DefaultFileSystem(baseDir);
when(context.fileSystem()).thenReturn(fileSystem);
}


+ 1
- 1
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java View File

@@ -52,7 +52,7 @@ public class SyntaxHighlightingSensorTest {
public void prepare() throws IOException {
baseDir = temp.newFolder();
sensor = new SyntaxHighlightingSensor();
fileSystem = new DefaultFileSystem();
fileSystem = new DefaultFileSystem(baseDir);
when(context.fileSystem()).thenReturn(fileSystem);
}


+ 1
- 1
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/TestCaseSensorTest.java View File

@@ -56,7 +56,7 @@ public class TestCaseSensorTest {
public void prepare() throws IOException {
baseDir = temp.newFolder();
sensor = new TestCaseSensor();
fileSystem = new DefaultFileSystem();
fileSystem = new DefaultFileSystem(baseDir);
when(context.fileSystem()).thenReturn(fileSystem);
}


+ 1
- 1
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/XooTokenizerSensorTest.java View File

@@ -57,7 +57,7 @@ public class XooTokenizerSensorTest {
public void prepare() throws IOException {
baseDir = temp.newFolder();
sensor = new XooTokenizerSensor();
fileSystem = new DefaultFileSystem();
fileSystem = new DefaultFileSystem(baseDir);
when(context.fileSystem()).thenReturn(fileSystem);
settings = new Settings();
when(context.settings()).thenReturn(settings);

+ 11
- 4
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java View File

@@ -19,7 +19,9 @@
*/
package org.sonar.xoo.rule;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -34,6 +36,8 @@ import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
import org.sonar.api.config.Settings;
import org.sonar.xoo.Xoo;

import java.io.IOException;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -42,6 +46,9 @@ import static org.mockito.Mockito.when;

public class OneIssuePerLineSensorTest {

@Rule
public TemporaryFolder temp = new TemporaryFolder();

private OneIssuePerLineSensor sensor = new OneIssuePerLineSensor();

@Test
@@ -52,8 +59,8 @@ public class OneIssuePerLineSensorTest {
}

@Test
public void testRule() {
DefaultFileSystem fs = new DefaultFileSystem();
public void testRule() throws IOException {
DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder());
DefaultInputFile inputFile = new DefaultInputFile("foo", "src/Foo.xoo").setLanguage(Xoo.KEY).setLines(10);
fs.add(inputFile);

@@ -76,8 +83,8 @@ public class OneIssuePerLineSensorTest {
}

@Test
public void testForceSeverity() {
DefaultFileSystem fs = new DefaultFileSystem();
public void testForceSeverity() throws IOException {
DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder());
DefaultInputFile inputFile = new DefaultInputFile("foo", "src/Foo.xoo").setLanguage(Xoo.KEY).setLines(10);
fs.add(inputFile);


+ 1
- 1
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/scm/XooBlameCommandTest.java View File

@@ -57,7 +57,7 @@ public class XooBlameCommandTest {
@Before
public void prepare() throws IOException {
baseDir = temp.newFolder();
fs = new DefaultFileSystem();
fs = new DefaultFileSystem(baseDir);
input = mock(BlameInput.class);
when(input.fileSystem()).thenReturn(fs);
}

+ 18
- 0
sonar-batch/pom.xml View File

@@ -9,6 +9,10 @@

<artifactId>sonar-batch</artifactId>
<name>SonarQube :: Batch</name>
<properties>
<enableBenchmarkAssertions>false</enableBenchmarkAssertions>
</properties>

<dependencies>
<dependency>
@@ -197,4 +201,18 @@
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>runBenchmarks</id>
<activation>
<property>
<name>runBenchmarks</name>
</property>
</activation>
<properties>
<enableBenchmarkAssertions>true</enableBenchmarkAssertions>
</properties>
</profile>
</profiles>
</project>

+ 0
- 10
sonar-batch/src/main/java/org/sonar/batch/maven/MavenProjectConverter.java View File

@@ -36,7 +36,6 @@ import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.maven.MavenUtils;
import org.sonar.api.task.TaskExtension;
import org.sonar.api.utils.MessageException;
import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
import org.sonar.java.api.JavaUtils;

import javax.annotation.Nullable;
@@ -219,15 +218,6 @@ public class MavenProjectConverter implements TaskExtension {
return resolvePath(pom.getBuild().getDirectory(), pom.getBasedir());
}

public void synchronizeFileSystem(MavenProject pom, DefaultModuleFileSystem into) {
into.resetDirs(
pom.getBasedir(),
getBuildDir(pom),
mainDirs(pom),
testDirs(pom),
Arrays.asList(resolvePath(pom.getBuild().getOutputDirectory(), pom.getBasedir())));
}

static File resolvePath(@Nullable String path, File basedir) {
if (path != null) {
File file = new File(StringUtils.trim(path));

+ 5
- 5
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicates.java View File

@@ -20,7 +20,7 @@
package org.sonar.batch.scan.filesystem;

import org.apache.commons.io.FilenameUtils;
import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.AbstractFilePredicate;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;

@@ -34,7 +34,7 @@ class AdditionalFilePredicates {
// only static inner classes
}

static class KeyPredicate implements FilePredicate {
static class KeyPredicate extends AbstractFilePredicate {
private final String key;

KeyPredicate(String key) {
@@ -47,7 +47,7 @@ class AdditionalFilePredicates {
}
}

static class DeprecatedKeyPredicate implements FilePredicate {
static class DeprecatedKeyPredicate extends AbstractFilePredicate {
private final String key;

DeprecatedKeyPredicate(String key) {
@@ -60,7 +60,7 @@ class AdditionalFilePredicates {
}
}

static class SourceRelativePathPredicate implements FilePredicate {
static class SourceRelativePathPredicate extends AbstractFilePredicate {
private final String path;

SourceRelativePathPredicate(String s) {
@@ -73,7 +73,7 @@ class AdditionalFilePredicates {
}
}

static class SourceDirPredicate implements FilePredicate {
static class SourceDirPredicate extends AbstractFilePredicate {
private final String path;

SourceDirPredicate(String s) {

+ 1
- 25
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java View File

@@ -80,14 +80,11 @@ public class DefaultModuleFileSystem extends DefaultFileSystem implements Module
private DefaultModuleFileSystem(ModuleInputFileCache moduleInputFileCache, String moduleKey, Settings settings,
FileIndexer indexer, ModuleFileSystemInitializer initializer,
@Nullable ComponentIndexer componentIndexer) {
super(moduleInputFileCache);
super(initializer.baseDir(), moduleInputFileCache);
this.componentIndexer = componentIndexer;
this.moduleKey = moduleKey;
this.settings = settings;
this.indexer = indexer;
if (initializer.baseDir() != null) {
setBaseDir(initializer.baseDir());
}
setWorkDir(initializer.workingDir());
this.buildDir = initializer.buildDir();
this.sourceDirsOrFiles = initializer.sources();
@@ -219,17 +216,6 @@ public class DefaultModuleFileSystem extends DefaultFileSystem implements Module
}
}

public void resetDirs(File basedir, File buildDir, List<File> sourceDirs, List<File> testDirs, List<File> binaryDirs) {
if (initialized) {
throw MessageException.of("Module filesystem is already initialized. Modifications of filesystem are only allowed during Initializer phase.");
}
setBaseDir(basedir);
this.buildDir = buildDir;
this.sourceDirsOrFiles = existingDirsOrFiles(sourceDirs);
this.testDirsOrFiles = existingDirsOrFiles(testDirs);
this.binaryDirs = existingDirsOrFiles(binaryDirs);
}

public void index() {
if (initialized) {
throw MessageException.of("Module filesystem can only be indexed once");
@@ -241,16 +227,6 @@ public class DefaultModuleFileSystem extends DefaultFileSystem implements Module
}
}

private List<File> existingDirsOrFiles(List<File> dirsOrFiles) {
ImmutableList.Builder<File> builder = ImmutableList.builder();
for (File dirOrFile : dirsOrFiles) {
if (dirOrFile.exists()) {
builder.add(dirOrFile);
}
}
return builder.build();
}

private FilePredicate fromDeprecatedAttribute(String key, Collection<String> value) {
if ("TYPE".equals(key)) {
return predicates().or(Collections2.transform(value, new Function<String, FilePredicate>() {

+ 4
- 5
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleInputFileCache.java View File

@@ -24,7 +24,6 @@ import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.InputDir;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.batch.fs.internal.RelativePathPredicate;

public class ModuleInputFileCache extends DefaultFileSystem.Cache implements BatchComponent {

@@ -37,17 +36,17 @@ public class ModuleInputFileCache extends DefaultFileSystem.Cache implements Bat
}

@Override
protected Iterable<InputFile> inputFiles() {
public Iterable<InputFile> inputFiles() {
return projectCache.filesByModule(moduleKey);
}

@Override
protected InputFile inputFile(RelativePathPredicate predicate) {
return projectCache.getFile(moduleKey, predicate.path());
public InputFile inputFile(String relativePath) {
return projectCache.getFile(moduleKey, relativePath);
}

@Override
protected InputDir inputDir(String relativePath) {
public InputDir inputDir(String relativePath) {
return projectCache.getDir(moduleKey, relativePath);
}


+ 1
- 1
sonar-batch/src/test/java/org/sonar/batch/debt/SqaleRatingDecoratorTest.java View File

@@ -73,7 +73,7 @@ public class SqaleRatingDecoratorTest {
public void setUp() throws Exception {
settings = new Settings();

fs = new DefaultFileSystem();
fs = new DefaultFileSystem(temp.newFolder());
fs.add(new DefaultInputFile("foo", file.getPath())
.setLanguage("java")
.setFile(temp.newFile("Foo.java")));

+ 5
- 4
sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java View File

@@ -65,13 +65,14 @@ public class IssueExclusionsLoaderTest {
@Mock
private PatternMatcher patternMatcher;

DefaultFileSystem fs = new DefaultFileSystem().setEncoding(UTF_8);
IssueExclusionsLoader scanner;
File baseDir;
private DefaultFileSystem fs;
private IssueExclusionsLoader scanner;
private File baseDir;

@Before
public void before() throws IOException {
public void before() throws Exception {
baseDir = temp.newFolder();
fs = new DefaultFileSystem(baseDir).setEncoding(UTF_8);
MockitoAnnotations.initMocks(this);
scanner = new IssueExclusionsLoader(regexpScanner, exclusionPatternInitializer, inclusionPatternInitializer, fs);
}

+ 49
- 0
sonar-batch/src/test/java/org/sonar/batch/mediumtest/Benchmark.java View File

@@ -0,0 +1,49 @@
/*
* 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;

import org.hamcrest.Matchers;
import org.junit.rules.ErrorCollector;
import org.slf4j.LoggerFactory;

public class Benchmark extends ErrorCollector {

private static final boolean ENABLED = "true".equals(System.getProperty("enableBenchmarkAssertions"));

static {
if (ENABLED) {
LoggerFactory.getLogger(Benchmark.class).warn("Assertions are calibrated for SonarSource dedicated box. " +
"They can be disabled by setting the property -DenableBenchmarkAssertions=false.");
}
}

public void expectBetween(String label, long val, long min, long max) {
if (ENABLED) {
checkThat(label, val, Matchers.allOf(Matchers.greaterThan(min), Matchers.lessThan(max)));
}
}

public void expectLessThanOrEqualTo(String label, long val, long max) {
if (ENABLED) {
checkThat(label, val, Matchers.lessThan(max));
}
}

}

+ 136
- 0
sonar-batch/src/test/java/org/sonar/batch/mediumtest/fs/RandomFsAccessMediumTest.java View File

@@ -0,0 +1,136 @@
/*
* 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.base.Charsets;
import com.google.common.collect.ImmutableMap;
import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.batch.mediumtest.BatchMediumTester;
import org.sonar.batch.mediumtest.Benchmark;
import org.sonar.batch.mediumtest.TaskResult;
import org.sonar.batch.protocol.input.ActiveRule;
import org.sonar.xoo.XooPlugin;

import java.io.File;
import java.io.IOException;

import static org.assertj.core.api.Assertions.assertThat;

public class RandomFsAccessMediumTest {

@Rule
public TemporaryFolder temp = new TemporaryFolder();

@Rule
public Benchmark bench = new Benchmark();

public BatchMediumTester tester = BatchMediumTester.builder()
.registerPlugin("xoo", new XooPlugin())
.addDefaultQProfile("xoo", "Sonar Way")
.activateRule(new ActiveRule("xoo", "RandomAccessIssue", null, "One issue per line", "MAJOR", null, "xoo"))
.build();

@Before
public void prepare() {
tester.start();
}

@After
public void stop() {
tester.stop();
}

@Test
public void testRandomFsAccessByAbsolutePath() throws IOException {

File baseDir = temp.newFolder();
File srcDir = prepareBigProject(baseDir);

File paths = new File(baseDir, "paths.txt");
int ISSUE_COUNT = 10000;
for (int i = 0; i < ISSUE_COUNT; i++) {
File xooFile = new File(srcDir, "sample" + (i / 10 + 1) + ".xoo");
FileUtils.write(paths, xooFile.getAbsolutePath() + "\n", Charsets.UTF_8, true);
}

long start = System.currentTimeMillis();
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")
.put("sonar.xoo.randomAccessIssue.paths", paths.getAbsolutePath())
.build())
.start();

assertThat(result.issues()).hasSize(ISSUE_COUNT);
bench.expectLessThanOrEqualTo("Time to create " + ISSUE_COUNT + " issues on random files using FileSystem query", System.currentTimeMillis() - start, 2000);
}

@Test
public void testRandomFsAccessByRelativePath() throws IOException {

File baseDir = temp.newFolder();
File srcDir = prepareBigProject(baseDir);

File paths = new File(baseDir, "paths.txt");
int ISSUE_COUNT = 10000;
for (int i = 0; i < ISSUE_COUNT; i++) {
FileUtils.write(paths, "src/sample" + (i / 10 + 1) + ".xoo\n", Charsets.UTF_8, true);
}

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")
.put("sonar.xoo.randomAccessIssue.paths", paths.getAbsolutePath())
.build())
.start();

assertThat(result.issues()).hasSize(ISSUE_COUNT);

}

private File prepareBigProject(File baseDir) throws IOException {
File srcDir = new File(baseDir, "src");
srcDir.mkdir();

for (int i = 1; i <= 1000; i++) {
File xooFile = new File(srcDir, "sample" + i + ".xoo");
FileUtils.write(xooFile, "foo");
}
return srcDir;
}

}

+ 15
- 2
sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java View File

@@ -19,7 +19,10 @@
*/
package org.sonar.batch.rule;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.measures.CoreMetrics;
@@ -32,10 +35,15 @@ import java.util.Date;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class QProfileSensorTest {

@Rule
public TemporaryFolder temp = new TemporaryFolder();

static final Date DATE = UtcDateUtils.parseDateTime("2014-01-15T12:00:00+0000");
static final QProfile JAVA_PROFILE = new QProfile().setKey("java-two").setName("Java Two").setLanguage("java")
.setRulesUpdatedAt(DATE);
@@ -45,7 +53,12 @@ public class QProfileSensorTest {
ModuleQProfiles moduleQProfiles = mock(ModuleQProfiles.class);
Project project = mock(Project.class);
SensorContext sensorContext = mock(SensorContext.class);
DefaultFileSystem fs = new DefaultFileSystem();
DefaultFileSystem fs;

@Before
public void prepare() throws Exception {
fs = new DefaultFileSystem(temp.newFolder());
}

@Test
public void to_string() throws Exception {

+ 12
- 5
sonar-batch/src/test/java/org/sonar/batch/rule/QProfileVerifierTest.java View File

@@ -23,24 +23,31 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.slf4j.Logger;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.config.Settings;
import org.sonar.api.utils.MessageException;

import static org.mockito.Mockito.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class QProfileVerifierTest {

@Rule
public TemporaryFolder temp = new TemporaryFolder();

@Rule
public ExpectedException thrown = ExpectedException.none();

DefaultFileSystem fs = new DefaultFileSystem();
ModuleQProfiles profiles;
Settings settings = new Settings();
private DefaultFileSystem fs;
private ModuleQProfiles profiles;
private Settings settings = new Settings();

@Before
public void before() {
public void before() throws Exception {
fs = new DefaultFileSystem(temp.newFolder());
profiles = mock(ModuleQProfiles.class);
QProfile javaProfile = new QProfile().setKey("p1").setName("My Java profile").setLanguage("java");
when(profiles.findByLanguage("java")).thenReturn(javaProfile);

+ 13
- 3
sonar-batch/src/test/java/org/sonar/batch/scan/LanguageVerifierTest.java View File

@@ -19,9 +19,11 @@
*/
package org.sonar.batch.scan;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.Java;
@@ -34,13 +36,21 @@ import static org.assertj.core.api.Assertions.assertThat;

public class LanguageVerifierTest {

Settings settings = new Settings();
LanguagesReferential languages = new DefaultLanguagesReferential(new Languages(Java.INSTANCE));
DefaultFileSystem fs = new DefaultFileSystem();
@Rule
public TemporaryFolder temp = new TemporaryFolder();

@Rule
public ExpectedException thrown = ExpectedException.none();

private Settings settings = new Settings();
private LanguagesReferential languages = new DefaultLanguagesReferential(new Languages(Java.INSTANCE));
private DefaultFileSystem fs;

@Before
public void prepare() throws Exception {
fs = new DefaultFileSystem(temp.newFolder());
}

@Test
public void language_is_not_set() throws Exception {
LanguageVerifier verifier = new LanguageVerifier(settings, languages, fs);

+ 2
- 1
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java View File

@@ -48,7 +48,7 @@ public class ComponentIndexerTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
private File baseDir;
private DefaultFileSystem fs = new DefaultFileSystem();
private DefaultFileSystem fs;
private SonarIndex sonarIndex;
private AbstractLanguage cobolLanguage;
private Project project;
@@ -56,6 +56,7 @@ public class ComponentIndexerTest {
@Before
public void prepare() throws IOException {
baseDir = temp.newFolder();
fs = new DefaultFileSystem(baseDir);
sonarIndex = mock(SonarIndex.class);
project = new Project("myProject");
cobolLanguage = new AbstractLanguage("cobol") {

+ 9
- 35
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java View File

@@ -58,13 +58,13 @@ public class DefaultModuleFileSystemTest {

@Test
public void test_equals_and_hashCode() throws Exception {
DefaultModuleFileSystem foo1 = new DefaultModuleFileSystem(moduleInputFileCache,
DefaultModuleFileSystem foo1 = new DefaultModuleFileSystem(moduleInputFileCache,
new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
DefaultModuleFileSystem foo2 = new DefaultModuleFileSystem(moduleInputFileCache,
DefaultModuleFileSystem foo2 = new DefaultModuleFileSystem(moduleInputFileCache,
new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
DefaultModuleFileSystem bar = new DefaultModuleFileSystem(moduleInputFileCache,
DefaultModuleFileSystem bar = new DefaultModuleFileSystem(moduleInputFileCache,
new Project("bar"), settings, fileIndexer, initializer, componentIndexer);
DefaultModuleFileSystem branch = new DefaultModuleFileSystem(moduleInputFileCache,
DefaultModuleFileSystem branch = new DefaultModuleFileSystem(moduleInputFileCache,
new Project("bar", "branch", "My project"), settings, fileIndexer, initializer, componentIndexer);

assertThat(foo1.moduleKey()).isEqualTo("foo");
@@ -79,7 +79,7 @@ public class DefaultModuleFileSystemTest {

@Test
public void default_source_encoding() {
DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
new Project("foo"), settings, fileIndexer, initializer, componentIndexer);

assertThat(fs.sourceCharset()).isEqualTo(Charset.defaultCharset());
@@ -89,7 +89,7 @@ public class DefaultModuleFileSystemTest {
@Test
public void source_encoding_is_set() {
settings.setProperty(CoreProperties.ENCODING_PROPERTY, "Cp1124");
DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
new Project("foo"), settings, fileIndexer, initializer, componentIndexer);

assertThat(fs.encoding()).isEqualTo(Charset.forName("Cp1124"));
@@ -119,7 +119,7 @@ public class DefaultModuleFileSystemTest {
javaTest.mkdirs();
when(initializer.tests()).thenReturn(Arrays.asList(javaTest, additionalTest));

DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
new Project("foo"), settings, fileIndexer, initializer, componentIndexer);

assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(basedir.getCanonicalPath());
@@ -130,35 +130,9 @@ public class DefaultModuleFileSystemTest {
assertThat(fs.binaryDirs()).hasSize(1);
}

@Test
public void should_reset_dirs() throws IOException {
File basedir = temp.newFolder();
when(initializer.baseDir()).thenReturn(basedir);
when(initializer.workingDir()).thenReturn(basedir);
when(initializer.sources()).thenReturn(Arrays.asList(new File(basedir, "src/main/java")));

DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
new Project("foo"), settings, fileIndexer, initializer, componentIndexer);

File existingDir = temp.newFolder("new_folder");
File notExistingDir = new File(existingDir, "not_exist");

fs.resetDirs(existingDir, existingDir,
Lists.newArrayList(existingDir, notExistingDir), Lists.newArrayList(existingDir, notExistingDir), Lists.newArrayList(existingDir, notExistingDir));

assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(existingDir.getCanonicalPath());
assertThat(fs.buildDir().getCanonicalPath()).isEqualTo(existingDir.getCanonicalPath());
assertThat(fs.sourceDirs()).hasSize(1);
assertThat(fs.sourceDirs().get(0).getCanonicalPath()).isEqualTo(existingDir.getCanonicalPath());
assertThat(fs.testDirs()).hasSize(1);
assertThat(fs.testDirs().get(0).getCanonicalPath()).isEqualTo(existingDir.getCanonicalPath());
assertThat(fs.binaryDirs()).hasSize(1);
assertThat(fs.binaryDirs().get(0).getCanonicalPath()).isEqualTo(existingDir.getCanonicalPath());
}

@Test
public void should_search_input_files() throws Exception {
DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
new Project("foo"), settings, fileIndexer, initializer, componentIndexer);

File mainFile = temp.newFile();
@@ -176,7 +150,7 @@ public class DefaultModuleFileSystemTest {

@Test
public void should_index() throws Exception {
DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
new Project("foo"), settings, fileIndexer, initializer, componentIndexer);

verifyZeroInteractions(fileIndexer);

+ 5
- 4
sonar-batch/src/test/java/org/sonar/batch/scan/report/JSONReportTest.java View File

@@ -64,11 +64,11 @@ public class JSONReportTest {
private SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

@org.junit.Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
public TemporaryFolder temp = new TemporaryFolder();

JSONReport jsonReport;
Resource resource = mock(Resource.class);
DefaultFileSystem fs = new DefaultFileSystem();
DefaultFileSystem fs;
Server server = mock(Server.class);
ActiveRules activeRules = mock(ActiveRules.class);
Settings settings = new Settings();
@@ -76,7 +76,8 @@ public class JSONReportTest {
private UserRepository userRepository;

@Before
public void before() {
public void before() throws Exception {
fs = new DefaultFileSystem(temp.newFolder());
SIMPLE_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+02:00"));
when(resource.getEffectiveKey()).thenReturn("Action.java");
when(server.getVersion()).thenReturn("3.6");
@@ -161,7 +162,7 @@ public class JSONReportTest {

@Test
public void should_export_issues_to_file() throws IOException {
File workDir = temporaryFolder.newFolder("sonar");
File workDir = temp.newFolder("sonar");
fs.setWorkDir(workDir);

when(jsonReport.getIssues()).thenReturn(Collections.<DefaultIssue>emptyList());

+ 7
- 4
sonar-batch/src/test/java/org/sonar/batch/sensor/AnalyzerOptimizerTest.java View File

@@ -23,6 +23,7 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.AnalysisMode;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
@@ -39,18 +40,20 @@ import static org.mockito.Mockito.when;

public class AnalyzerOptimizerTest {

DefaultFileSystem fs = new DefaultFileSystem();
@Rule
public TemporaryFolder temp = new TemporaryFolder();

@Rule
public ExpectedException thrown = ExpectedException.none();
private AnalyzerOptimizer optimizer;

private DefaultFileSystem fs;
private AnalyzerOptimizer optimizer;
private Settings settings;

private AnalysisMode analysisMode;

@Before
public void prepare() {
public void prepare() throws Exception {
fs = new DefaultFileSystem(temp.newFolder());
settings = new Settings();
analysisMode = mock(AnalysisMode.class);
optimizer = new AnalyzerOptimizer(fs, new ActiveRulesBuilder().build(), settings, analysisMode);

+ 6
- 2
sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorContextTest.java View File

@@ -23,6 +23,7 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.AnalysisMode;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.batch.measure.MetricFinder;
@@ -41,6 +42,9 @@ import static org.mockito.Mockito.when;

public class DefaultSensorContextTest {

@Rule
public TemporaryFolder temp = new TemporaryFolder();

@Rule
public ExpectedException thrown = ExpectedException.none();

@@ -52,9 +56,9 @@ public class DefaultSensorContextTest {
private AnalysisMode analysisMode;

@Before
public void prepare() {
public void prepare() throws Exception {
activeRules = new ActiveRulesBuilder().build();
fs = new DefaultFileSystem();
fs = new DefaultFileSystem(temp.newFolder());
MetricFinder metricFinder = mock(MetricFinder.class);
when(metricFinder.findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC);
when(metricFinder.findByKey(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY)).thenReturn(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);

+ 6
- 2
sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java View File

@@ -23,6 +23,7 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.mockito.ArgumentCaptor;
import org.sonar.api.batch.fs.InputDir;
import org.sonar.api.batch.fs.InputFile;
@@ -66,6 +67,9 @@ import static org.mockito.Mockito.when;

public class DefaultSensorStorageTest {

@Rule
public TemporaryFolder temp = new TemporaryFolder();

@Rule
public ExpectedException thrown = ExpectedException.none();

@@ -78,9 +82,9 @@ public class DefaultSensorStorageTest {
private DefaultIndex sonarIndex;

@Before
public void prepare() {
public void prepare() throws Exception {
activeRules = new ActiveRulesBuilder().build();
fs = new DefaultFileSystem();
fs = new DefaultFileSystem(temp.newFolder());
MetricFinder metricFinder = mock(MetricFinder.class);
when(metricFinder.findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC);
when(metricFinder.findByKey(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY)).thenReturn(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);

+ 60
- 0
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AbstractFilePredicate.java View File

@@ -0,0 +1,60 @@
/*
* 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.api.batch.fs;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import org.sonar.api.batch.fs.FileSystem.Index;

/**
* Partial implementation of {@link FilePredicate}.
* @since 5.1
*/
public abstract class AbstractFilePredicate implements FilePredicate {

protected static final int DEFAULT_PRIORITY = 10;
protected static final int USE_INDEX = 20;

@Override
public Iterable<InputFile> filter(Iterable<InputFile> target) {
return Iterables.filter(target, new Predicate<InputFile>() {
@Override
public boolean apply(InputFile input) {
return AbstractFilePredicate.this.apply(input);
}
});
}

@Override
public Iterable<InputFile> get(Index index) {
return filter(index.inputFiles());
}

@Override
public int priority() {
return DEFAULT_PRIORITY;
}

@Override
public int compareTo(FilePredicate o) {
return o.priority() - priority();
}

}

+ 25
- 1
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java View File

@@ -19,11 +19,35 @@
*/
package org.sonar.api.batch.fs;

import org.sonar.api.batch.fs.internal.RelativePathPredicate;

/**
* Determines if a file must be kept in search results. See {@link org.sonar.api.batch.fs.FileSystem}
* and {@link org.sonar.api.batch.fs.FilePredicates}.
* @since 4.2
*/
public interface FilePredicate {
public interface FilePredicate extends Comparable<FilePredicate> {
/**
* Test if provided file is valid for this predicate
*/
boolean apply(InputFile inputFile);

/**
* Filter provided files to keep only the ones that are valid for this predicate
*/
Iterable<InputFile> filter(Iterable<InputFile> inputFiles);

/**
* Get all files that are valid for this predicate.
*/
Iterable<InputFile> get(FileSystem.Index index);

/**
* For optimization. FilePredicates will be applied in priority order. For example when doing
* p.and(p1, p2, p3) then p1, p2 and p3 will be applied according to their priority value. Higher priority value
* are applied first.
* Assign a high priority when the predicate will likely highly reduce the set of InputFiles to filter. Also
* {@link RelativePathPredicate} and AbsolutePathPredicate have a high priority since they are using cache index.
*/
int priority();
}

+ 13
- 0
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java View File

@@ -149,4 +149,17 @@ public interface FileSystem extends BatchComponent {
* @since 5.0
*/
File resolvePath(String path);

/**
* Interface of the underlying file index.
*/
public static interface Index {
Iterable<InputFile> inputFiles();

@CheckForNull
InputFile inputFile(String relativePath);

@CheckForNull
InputDir inputDir(String relativePath);
}
}

+ 26
- 3
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbsolutePathPredicate.java View File

@@ -19,18 +19,26 @@
*/
package org.sonar.api.batch.fs.internal;

import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.AbstractFilePredicate;
import org.sonar.api.batch.fs.FileSystem.Index;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.api.utils.PathUtils;

import java.io.File;
import java.util.Arrays;
import java.util.Collections;

/**
* @since 4.2
*/
class AbsolutePathPredicate implements FilePredicate {
class AbsolutePathPredicate extends AbstractFilePredicate {

private final String path;
private final File baseDir;

AbsolutePathPredicate(String path) {
AbsolutePathPredicate(String path, File baseDir) {
this.baseDir = baseDir;
this.path = PathUtils.sanitize(path);
}

@@ -38,4 +46,19 @@ class AbsolutePathPredicate implements FilePredicate {
public boolean apply(InputFile f) {
return path.equals(f.absolutePath());
}

@Override
public Iterable<InputFile> get(Index index) {
String relative = PathUtils.sanitize(new PathResolver().relativePath(baseDir, new File(path)));
if (relative == null) {
return Collections.<InputFile>emptyList();
}
InputFile f = index.inputFile(relative);
return f != null ? Arrays.asList(f) : Collections.<InputFile>emptyList();
}

@Override
public int priority() {
return USE_INDEX;
}
}

+ 56
- 4
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AndPredicate.java View File

@@ -19,20 +19,45 @@
*/
package org.sonar.api.batch.fs.internal;

import com.google.common.annotations.VisibleForTesting;
import org.sonar.api.batch.fs.AbstractFilePredicate;
import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.FileSystem.Index;
import org.sonar.api.batch.fs.InputFile;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
* @since 4.2
*/
class AndPredicate implements FilePredicate {
class AndPredicate extends AbstractFilePredicate {

private final Collection<FilePredicate> predicates;
private final List<FilePredicate> predicates = new ArrayList<>();

AndPredicate(Collection<FilePredicate> predicates) {
this.predicates = predicates;
private AndPredicate() {
}

public static FilePredicate create(Collection<FilePredicate> predicates) {
if (predicates.isEmpty()) {
return TruePredicate.TRUE;
}
AndPredicate result = new AndPredicate();
for (FilePredicate filePredicate : predicates) {
if (filePredicate == TruePredicate.TRUE) {
continue;
} else if (filePredicate == FalsePredicate.FALSE) {
return FalsePredicate.FALSE;
} else if (filePredicate instanceof AndPredicate) {
result.predicates.addAll(((AndPredicate) filePredicate).predicates);
} else {
result.predicates.add(filePredicate);
}
}
Collections.sort(result.predicates);
return result;
}

@Override
@@ -45,4 +70,31 @@ class AndPredicate implements FilePredicate {
return true;
}

@Override
public Iterable<InputFile> filter(Iterable<InputFile> target) {
Iterable<InputFile> result = target;
for (FilePredicate predicate : predicates) {
result = predicate.filter(result);
}
return result;
}

@Override
public Iterable<InputFile> get(Index index) {
if (predicates.isEmpty()) {
return index.inputFiles();
}
// Optimization, use get on first predicate then filter with next predicates
Iterable<InputFile> result = predicates.get(0).get(index);
for (int i = 1; i < predicates.size(); i++) {
result = predicates.get(i).filter(result);
}
return result;
}

@VisibleForTesting
Collection<FilePredicate> predicates() {
return predicates;
}

}

+ 13
- 12
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFilePredicates.java View File

@@ -35,10 +35,14 @@ import java.util.List;
* @since 4.2
*/
public class DefaultFilePredicates implements FilePredicates {

private final File baseDir;

/**
* Client code should use {@link org.sonar.api.batch.fs.FileSystem#predicates()} to get an instance
*/
DefaultFilePredicates() {
DefaultFilePredicates(File baseDir) {
this.baseDir = baseDir;
}

/**
@@ -57,16 +61,13 @@ public class DefaultFilePredicates implements FilePredicates {
return FalsePredicate.FALSE;
}

/**
* Warning - not efficient because absolute path is not indexed yet.
*/
@Override
public FilePredicate hasAbsolutePath(String s) {
return new AbsolutePathPredicate(s);
return new AbsolutePathPredicate(s, baseDir);
}

/**
* TODO document that non-normalized path and Windows-style path are supported
* non-normalized path and Windows-style path are supported
*/
@Override
public FilePredicate hasRelativePath(String s) {
@@ -160,31 +161,31 @@ public class DefaultFilePredicates implements FilePredicates {

@Override
public FilePredicate or(Collection<FilePredicate> or) {
return new OrPredicate(or);
return OrPredicate.create(or);
}

@Override
public FilePredicate or(FilePredicate... or) {
return new OrPredicate(Arrays.asList(or));
return OrPredicate.create(Arrays.asList(or));
}

@Override
public FilePredicate or(FilePredicate first, FilePredicate second) {
return new OrPredicate(Arrays.asList(first, second));
return OrPredicate.create(Arrays.asList(first, second));
}

@Override
public FilePredicate and(Collection<FilePredicate> and) {
return new AndPredicate(and);
return AndPredicate.create(and);
}

@Override
public FilePredicate and(FilePredicate... and) {
return new AndPredicate(Arrays.asList(and));
return AndPredicate.create(Arrays.asList(and));
}

@Override
public FilePredicate and(FilePredicate first, FilePredicate second) {
return new AndPredicate(Arrays.asList(first, second));
return AndPredicate.create(Arrays.asList(first, second));
}
}

+ 28
- 46
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java View File

@@ -19,7 +19,9 @@
*/
package org.sonar.api.batch.fs.internal;

import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.FileSystem;
@@ -35,7 +37,6 @@ import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
@@ -50,25 +51,23 @@ public class DefaultFileSystem implements FileSystem {

private final Cache cache;
private final SortedSet<String> languages = new TreeSet<String>();
private File baseDir, workDir;
private final File baseDir;
private File workDir;
private Charset encoding;
private final FilePredicates predicates = new DefaultFilePredicates();
private final FilePredicates predicates;

/**
* Only for testing
*/
public DefaultFileSystem() {
this.cache = new MapCache();
public DefaultFileSystem(File baseDir) {
this(baseDir, new MapCache());
}

protected DefaultFileSystem(Cache cache) {
protected DefaultFileSystem(File baseDir, Cache cache) {
Preconditions.checkNotNull(baseDir, "Base directory can't be null");
this.baseDir = baseDir.getAbsoluteFile();
this.cache = cache;
}

public DefaultFileSystem setBaseDir(File d) {
Preconditions.checkNotNull(d, "Base directory can't be null");
this.baseDir = d.getAbsoluteFile();
return this;
this.predicates = new DefaultFilePredicates(baseDir);
}

@Override
@@ -102,10 +101,6 @@ public class DefaultFileSystem implements FileSystem {

@Override
public InputFile inputFile(FilePredicate predicate) {
doPreloadFiles();
if (predicate instanceof RelativePathPredicate) {
return cache.inputFile((RelativePathPredicate) predicate);
}
Iterable<InputFile> files = inputFiles(predicate);
Iterator<InputFile> iterator = files.iterator();
if (!iterator.hasNext()) {
@@ -133,30 +128,24 @@ public class DefaultFileSystem implements FileSystem {
@Override
public Iterable<InputFile> inputFiles(FilePredicate predicate) {
doPreloadFiles();
return filter(cache.inputFiles(), predicate);
return predicate.get(cache);
}

@Override
public boolean hasFiles(FilePredicate predicate) {
doPreloadFiles();
for (InputFile element : cache.inputFiles()) {
if (predicate.apply(element)) {
return true;
}
}
return false;
return predicate.get(cache).iterator().hasNext();
}

@Override
public Iterable<File> files(FilePredicate predicate) {
doPreloadFiles();
Collection<File> result = new ArrayList<File>();
for (InputFile element : inputFiles(predicate)) {
if (predicate.apply(element)) {
result.add(element.file());
return Iterables.transform(inputFiles(predicate), new Function<InputFile, File>() {
@Override
public File apply(InputFile input) {
return input.file();
}
}
return result;
});
}

@Override
@@ -169,16 +158,6 @@ public class DefaultFileSystem implements FileSystem {
return cache.inputDir(relativePath);
}

public static Collection<InputFile> filter(Iterable<InputFile> target, FilePredicate predicate) {
Collection<InputFile> result = new ArrayList<InputFile>();
for (InputFile element : target) {
if (predicate.apply(element)) {
result.add(element);
}
}
return result;
}

/**
* Adds InputFile to the list and registers its language, if present.
* Synchronized because PersistIt Exchange is not concurrent
@@ -228,14 +207,17 @@ public class DefaultFileSystem implements FileSystem {
// nothing to do by default
}

public abstract static class Cache {
protected abstract Iterable<InputFile> inputFiles();
public abstract static class Cache implements Index {
@Override
public abstract Iterable<InputFile> inputFiles();

@Override
@CheckForNull
protected abstract InputFile inputFile(RelativePathPredicate predicate);
public abstract InputFile inputFile(String relativePath);

@Override
@CheckForNull
protected abstract InputDir inputDir(String relativePath);
public abstract InputDir inputDir(String relativePath);

protected abstract void doAdd(InputFile inputFile);

@@ -264,12 +246,12 @@ public class DefaultFileSystem implements FileSystem {
}

@Override
public InputFile inputFile(RelativePathPredicate predicate) {
return fileMap.get(predicate.path());
public InputFile inputFile(String relativePath) {
return fileMap.get(relativePath);
}

@Override
protected InputDir inputDir(String relativePath) {
public InputDir inputDir(String relativePath) {
return dirMap.get(relativePath);
}


+ 15
- 1
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FalsePredicate.java View File

@@ -19,10 +19,14 @@
*/
package org.sonar.api.batch.fs.internal;

import org.sonar.api.batch.fs.AbstractFilePredicate;
import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.FileSystem.Index;
import org.sonar.api.batch.fs.InputFile;

class FalsePredicate implements FilePredicate {
import java.util.Collections;

class FalsePredicate extends AbstractFilePredicate {

static final FilePredicate FALSE = new FalsePredicate();

@@ -30,4 +34,14 @@ class FalsePredicate implements FilePredicate {
public boolean apply(InputFile inputFile) {
return false;
}

@Override
public Iterable<InputFile> filter(Iterable<InputFile> target) {
return Collections.emptyList();
}

@Override
public Iterable<InputFile> get(Index index) {
return Collections.emptyList();
}
}

+ 3
- 2
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/LanguagePredicate.java View File

@@ -19,13 +19,14 @@
*/
package org.sonar.api.batch.fs.internal;

import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.AbstractFilePredicate;

import org.sonar.api.batch.fs.InputFile;

/**
* @since 4.2
*/
class LanguagePredicate implements FilePredicate {
class LanguagePredicate extends AbstractFilePredicate {
private final String language;

LanguagePredicate(String language) {

+ 3
- 1
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/NotPredicate.java View File

@@ -19,13 +19,15 @@
*/
package org.sonar.api.batch.fs.internal;

import org.sonar.api.batch.fs.AbstractFilePredicate;

import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.InputFile;

/**
* @since 4.2
*/
class NotPredicate implements FilePredicate {
class NotPredicate extends AbstractFilePredicate {

private final FilePredicate predicate;


+ 28
- 7
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OrPredicate.java View File

@@ -19,25 +19,41 @@
*/
package org.sonar.api.batch.fs.internal;

import com.google.common.annotations.VisibleForTesting;
import org.sonar.api.batch.fs.AbstractFilePredicate;
import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.InputFile;

import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;

/**
* @since 4.2
*/
class OrPredicate implements FilePredicate {
class OrPredicate extends AbstractFilePredicate {

private final Collection<FilePredicate> predicates;
private final Collection<FilePredicate> predicates = new ArrayList<>();

OrPredicate(Collection<FilePredicate> predicates) {
private OrPredicate() {
}

public static FilePredicate create(Collection<FilePredicate> predicates) {
if (predicates.isEmpty()) {
this.predicates = Arrays.asList(TruePredicate.TRUE);
} else {
this.predicates = predicates;
return TruePredicate.TRUE;
}
OrPredicate result = new OrPredicate();
for (FilePredicate filePredicate : predicates) {
if (filePredicate == TruePredicate.TRUE) {
return TruePredicate.TRUE;
} else if (filePredicate == FalsePredicate.FALSE) {
continue;
} else if (filePredicate instanceof OrPredicate) {
result.predicates.addAll(((OrPredicate) filePredicate).predicates);
} else {
result.predicates.add(filePredicate);
}
}
return result;
}

@Override
@@ -50,4 +66,9 @@ class OrPredicate implements FilePredicate {
return false;
}

@VisibleForTesting
Collection<FilePredicate> predicates() {
return predicates;
}

}

+ 3
- 2
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPatternPredicate.java View File

@@ -19,13 +19,14 @@
*/
package org.sonar.api.batch.fs.internal;

import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.AbstractFilePredicate;

import org.sonar.api.batch.fs.InputFile;

/**
* @since 4.2
*/
class PathPatternPredicate implements FilePredicate {
class PathPatternPredicate extends AbstractFilePredicate {

private final PathPattern pattern;


+ 17
- 2
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathPredicate.java View File

@@ -19,14 +19,18 @@
*/
package org.sonar.api.batch.fs.internal;

import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.AbstractFilePredicate;
import org.sonar.api.batch.fs.FileSystem.Index;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.utils.PathUtils;

import java.util.Arrays;
import java.util.Collections;

/**
* @since 4.2
*/
public class RelativePathPredicate implements FilePredicate {
public class RelativePathPredicate extends AbstractFilePredicate {

private final String path;

@@ -43,4 +47,15 @@ public class RelativePathPredicate implements FilePredicate {
return path.equals(f.relativePath());
}

@Override
public Iterable<InputFile> get(Index index) {
InputFile f = index.inputFile(this.path);
return f != null ? Arrays.asList(f) : Collections.<InputFile>emptyList();
}

@Override
public int priority() {
return USE_INDEX;
}

}

+ 3
- 2
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/StatusPredicate.java View File

@@ -19,13 +19,14 @@
*/
package org.sonar.api.batch.fs.internal;

import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.AbstractFilePredicate;

import org.sonar.api.batch.fs.InputFile;

/**
* @since 4.2
*/
class StatusPredicate implements FilePredicate {
class StatusPredicate extends AbstractFilePredicate {

private final InputFile.Status status;


+ 13
- 1
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TruePredicate.java View File

@@ -19,10 +19,12 @@
*/
package org.sonar.api.batch.fs.internal;

import org.sonar.api.batch.fs.AbstractFilePredicate;
import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.FileSystem.Index;
import org.sonar.api.batch.fs.InputFile;

class TruePredicate implements FilePredicate {
class TruePredicate extends AbstractFilePredicate {

static final FilePredicate TRUE = new TruePredicate();

@@ -30,4 +32,14 @@ class TruePredicate implements FilePredicate {
public boolean apply(InputFile inputFile) {
return true;
}

@Override
public Iterable<InputFile> get(Index index) {
return index.inputFiles();
}

@Override
public Iterable<InputFile> filter(Iterable<InputFile> target) {
return target;
}
}

+ 3
- 3
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TypePredicate.java View File

@@ -19,13 +19,14 @@
*/
package org.sonar.api.batch.fs.internal;

import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.AbstractFilePredicate;

import org.sonar.api.batch.fs.InputFile;

/**
* @since 4.2
*/
class TypePredicate implements FilePredicate {
class TypePredicate extends AbstractFilePredicate {

private final InputFile.Type type;

@@ -39,4 +40,3 @@ class TypePredicate implements FilePredicate {
}

}


+ 75
- 0
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/AndPredicateTest.java View File

@@ -0,0 +1,75 @@
/*
* 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.api.batch.fs.internal;

import org.junit.Test;
import org.sonar.api.batch.fs.FilePredicate;

import java.util.Arrays;

import static org.assertj.core.api.Assertions.assertThat;

public class AndPredicateTest {

@Test
public void flattenNestedAnd() {
PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
PathPatternPredicate pathPatternPredicate3 = new PathPatternPredicate(PathPattern.create("foo3/**"));
FilePredicate andPredicate = AndPredicate.create(Arrays.<FilePredicate>asList(pathPatternPredicate1,
AndPredicate.create(Arrays.<FilePredicate>asList(pathPatternPredicate2, pathPatternPredicate3))));
assertThat(((AndPredicate) andPredicate).predicates()).containsExactly(pathPatternPredicate1, pathPatternPredicate2, pathPatternPredicate3);
}

@Test
public void sortPredicatesByPriority() {
PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
RelativePathPredicate relativePathPredicate = new RelativePathPredicate("foo");
FilePredicate andPredicate = AndPredicate.create(Arrays.<FilePredicate>asList(pathPatternPredicate1,
relativePathPredicate, pathPatternPredicate2));
assertThat(((AndPredicate) andPredicate).predicates()).containsExactly(relativePathPredicate, pathPatternPredicate1, pathPatternPredicate2);
}

@Test
public void simplifyAndExpressionsWhenEmpty() {
FilePredicate andPredicate = AndPredicate.create(Arrays.<FilePredicate>asList());
assertThat(andPredicate).isEqualTo(TruePredicate.TRUE);
}

@Test
public void simplifyAndExpressionsWhenTrue() {
PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
FilePredicate andPredicate = AndPredicate.create(Arrays.<FilePredicate>asList(pathPatternPredicate1,
TruePredicate.TRUE, pathPatternPredicate2));
assertThat(((AndPredicate) andPredicate).predicates()).containsExactly(pathPatternPredicate1, pathPatternPredicate2);
}

@Test
public void simplifyAndExpressionsWhenFalse() {
PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
FilePredicate andPredicate = AndPredicate.create(Arrays.<FilePredicate>asList(pathPatternPredicate1,
FalsePredicate.FALSE, pathPatternPredicate2));
assertThat(andPredicate).isEqualTo(FalsePredicate.FALSE);
}

}

+ 2
- 1
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java View File

@@ -41,10 +41,11 @@ public class DefaultFilePredicatesTest {
public TemporaryFolder temp = new TemporaryFolder();

DefaultInputFile javaFile;
FilePredicates predicates = new DefaultFilePredicates();
FilePredicates predicates;

@Before
public void before() throws IOException {
predicates = new DefaultFilePredicates(temp.newFolder());
javaFile = new DefaultInputFile("foo", "src/main/java/struts/Action.java")
.setFile(temp.newFile("Action.java"))
.setLanguage("java")

+ 11
- 13
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java View File

@@ -19,6 +19,7 @@
*/
package org.sonar.api.batch.fs.internal;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -37,12 +38,18 @@ public class DefaultFileSystemTest {
@Rule
public ExpectedException thrown = ExpectedException.none();

private DefaultFileSystem fs;

private File basedir;

@Before
public void prepare() throws Exception {
basedir = temp.newFolder();
fs = new DefaultFileSystem(basedir);
}

@Test
public void test_directories() throws Exception {
DefaultFileSystem fs = new DefaultFileSystem();

File basedir = temp.newFolder();
fs.setBaseDir(basedir);
assertThat(fs.baseDir()).isAbsolute().isDirectory().exists();
assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(basedir.getCanonicalPath());

@@ -54,8 +61,6 @@ public class DefaultFileSystemTest {

@Test
public void test_encoding() throws Exception {
DefaultFileSystem fs = new DefaultFileSystem();

assertThat(fs.isDefaultJvmEncoding()).isTrue();
assertThat(fs.encoding()).isEqualTo(Charset.defaultCharset());

@@ -66,8 +71,6 @@ public class DefaultFileSystemTest {

@Test
public void add_languages() throws Exception {
DefaultFileSystem fs = new DefaultFileSystem();

assertThat(fs.languages()).isEmpty();

fs.addLanguages("java", "php", "cobol");
@@ -76,8 +79,6 @@ public class DefaultFileSystemTest {

@Test
public void files() throws Exception {
DefaultFileSystem fs = new DefaultFileSystem();

assertThat(fs.inputFiles(fs.predicates().all())).isEmpty();

fs.add(new DefaultInputFile("foo", "src/Foo.php").setLanguage("php").setFile(temp.newFile()));
@@ -108,7 +109,6 @@ public class DefaultFileSystemTest {

@Test
public void input_file_returns_null_if_file_not_found() throws Exception {
DefaultFileSystem fs = new DefaultFileSystem();
assertThat(fs.inputFile(fs.predicates().hasRelativePath("src/Bar.java"))).isNull();
assertThat(fs.inputFile(fs.predicates().hasLanguage("cobol"))).isNull();
}
@@ -118,7 +118,6 @@ public class DefaultFileSystemTest {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("expected one element");

DefaultFileSystem fs = new DefaultFileSystem();
fs.add(new DefaultInputFile("foo", "src/Bar.java").setLanguage("java").setFile(temp.newFile()));
fs.add(new DefaultInputFile("foo", "src/Baz.java").setLanguage("java").setFile(temp.newFile()));

@@ -127,7 +126,6 @@ public class DefaultFileSystemTest {

@Test
public void input_file_supports_non_indexed_predicates() throws Exception {
DefaultFileSystem fs = new DefaultFileSystem();
fs.add(new DefaultInputFile("foo", "src/Bar.java").setLanguage("java").setFile(temp.newFile()));

// it would fail if more than one java file

+ 65
- 0
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/OrPredicateTest.java View File

@@ -0,0 +1,65 @@
/*
* 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.api.batch.fs.internal;

import org.junit.Test;
import org.sonar.api.batch.fs.FilePredicate;

import java.util.Arrays;

import static org.assertj.core.api.Assertions.assertThat;

public class OrPredicateTest {

@Test
public void flattenNestedOr() {
PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
PathPatternPredicate pathPatternPredicate3 = new PathPatternPredicate(PathPattern.create("foo3/**"));
FilePredicate orPredicate = OrPredicate.create(Arrays.<FilePredicate>asList(pathPatternPredicate1,
OrPredicate.create(Arrays.<FilePredicate>asList(pathPatternPredicate2, pathPatternPredicate3))));
assertThat(((OrPredicate) orPredicate).predicates()).containsExactly(pathPatternPredicate1, pathPatternPredicate2, pathPatternPredicate3);
}

@Test
public void simplifyOrExpressionsWhenEmpty() {
FilePredicate orPredicate = OrPredicate.create(Arrays.<FilePredicate>asList());
assertThat(orPredicate).isEqualTo(TruePredicate.TRUE);
}

@Test
public void simplifyOrExpressionsWhenFalse() {
PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
FilePredicate andPredicate = OrPredicate.create(Arrays.<FilePredicate>asList(pathPatternPredicate1,
FalsePredicate.FALSE, pathPatternPredicate2));
assertThat(((OrPredicate) andPredicate).predicates()).containsExactly(pathPatternPredicate1, pathPatternPredicate2);
}

@Test
public void simplifyAndExpressionsWhenTrue() {
PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
FilePredicate andPredicate = OrPredicate.create(Arrays.<FilePredicate>asList(pathPatternPredicate1,
TruePredicate.TRUE, pathPatternPredicate2));
assertThat(andPredicate).isEqualTo(TruePredicate.TRUE);
}

}

Loading…
Cancel
Save