Browse Source

SONAR-8832 Support project-level sensors (#1720)

tags/6.4-RC1
Janos Gyerik 7 years ago
parent
commit
bc298f9950
26 changed files with 407 additions and 107 deletions
  1. 12
    17
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java
  2. 8
    0
      sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TestInputFileBuilder.java
  3. 5
    0
      sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorDescriptor.java
  4. 11
    0
      sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/DefaultSensorDescriptor.java
  5. 4
    2
      sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java
  6. 20
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerExtensionDictionnary.java
  7. 2
    2
      sonar-scanner-engine/src/main/java/org/sonar/scanner/cpd/deprecated/DeprecatedCpdBlockIndexerSensor.java
  8. 39
    9
      sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/SensorsExecutor.java
  9. 3
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleScanContainer.java
  10. 1
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java
  11. 68
    10
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputComponentStore.java
  12. 29
    4
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStore.java
  13. 38
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/SensorStrategy.java
  14. 4
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/SensorWrapper.java
  15. 2
    1
      sonar-scanner-engine/src/main/java/org/sonar/scanner/source/CodeColorizerSensor.java
  16. 2
    1
      sonar-scanner-engine/src/main/java/org/sonar/scanner/source/ZeroCoverageSensor.java
  17. 52
    6
      sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerExtensionDictionnaryTest.java
  18. 3
    3
      sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdExecutorTest.java
  19. 14
    4
      sonar-scanner-engine/src/test/java/org/sonar/scanner/postjob/DefaultPostJobContextTest.java
  20. 7
    6
      sonar-scanner-engine/src/test/java/org/sonar/scanner/report/CoveragePublisherTest.java
  21. 8
    7
      sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MeasuresPublisherTest.java
  22. 7
    6
      sonar-scanner-engine/src/test/java/org/sonar/scanner/report/SourcePublisherTest.java
  23. 8
    3
      sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/QProfileVerifierTest.java
  24. 6
    5
      sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleIndexerTest.java
  25. 26
    13
      sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputComponentStoreTest.java
  26. 28
    8
      sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java

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

@@ -28,7 +28,6 @@ import java.nio.charset.Charset;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -53,7 +52,6 @@ import org.sonar.api.utils.PathUtils;
public class DefaultFileSystem implements FileSystem {

private final Cache cache;
private final SortedSet<String> languages = new TreeSet<>();
private final Path baseDir;
private Path workDir;
private Charset encoding;
@@ -192,10 +190,6 @@ public class DefaultFileSystem implements FileSystem {

public DefaultFileSystem add(InputFile inputFile) {
cache.add(inputFile);
String language = inputFile.language();
if (language != null) {
languages.add(language);
}
return this;
}

@@ -204,20 +198,10 @@ public class DefaultFileSystem implements FileSystem {
return this;
}

/**
* Adds a language to the list. To be used only for unit tests that need to use {@link #languages()} without
* using {@link #add(InputFile)}.
*/
public DefaultFileSystem addLanguages(String language, String... others) {
languages.add(language);
Collections.addAll(languages, others);
return this;
}

@Override
public SortedSet<String> languages() {
doPreloadFiles();
return languages;
return cache.languages();
}

@Override
@@ -245,6 +229,8 @@ public class DefaultFileSystem implements FileSystem {
public void add(InputDir inputDir) {
doAdd(inputDir);
}

protected abstract SortedSet<String> languages();
}

/**
@@ -255,6 +241,7 @@ public class DefaultFileSystem implements FileSystem {
private final Map<String, InputDir> dirMap = new HashMap<>();
private final SetMultimap<String, InputFile> filesByNameCache = LinkedHashMultimap.create();
private final SetMultimap<String, InputFile> filesByExtensionCache = LinkedHashMultimap.create();
private SortedSet<String> languages = new TreeSet<>();

@Override
public Iterable<InputFile> inputFiles() {
@@ -283,6 +270,9 @@ public class DefaultFileSystem implements FileSystem {

@Override
protected void doAdd(InputFile inputFile) {
if (inputFile.language() != null) {
languages.add(inputFile.language());
}
fileMap.put(inputFile.relativePath(), inputFile);
filesByNameCache.put(FilenamePredicate.getFilename(inputFile), inputFile);
filesByExtensionCache.put(FileExtensionPredicate.getExtension(inputFile), inputFile);
@@ -292,6 +282,11 @@ public class DefaultFileSystem implements FileSystem {
protected void doAdd(InputDir inputDir) {
dirMap.put(inputDir.relativePath(), inputDir);
}

@Override
protected SortedSet<String> languages() {
return languages;
}
}

@Override

+ 8
- 0
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TestInputFileBuilder.java View File

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

import java.io.File;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.Paths;

import javax.annotation.Nullable;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.utils.PathUtils;

@@ -143,4 +145,10 @@ public class TestInputFileBuilder {
inputFile.setPublish(publish);
return inputFile;
}

public static DefaultInputModule newDefaultInputModule(String moduleKey, File baseDir) {
ProjectDefinition definition = ProjectDefinition.create().setKey(moduleKey);
definition.setBaseDir(baseDir);
return new DefaultInputModule(definition, TestInputFileBuilder.nextBatchId());
}
}

+ 5
- 0
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorDescriptor.java View File

@@ -79,4 +79,9 @@ public interface SensorDescriptor {
*/
SensorDescriptor requireProperties(String... propertyKeys);

/**
* This sensor should be executed at the project level, instead of per-module.
* @since 6.4
*/
SensorDescriptor global();
}

+ 11
- 0
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/DefaultSensorDescriptor.java View File

@@ -32,6 +32,7 @@ public class DefaultSensorDescriptor implements SensorDescriptor {
private InputFile.Type type = null;
private String[] ruleRepositories = new String[0];
private String[] properties = new String[0];
private boolean global = false;

public String name() {
return name;
@@ -54,6 +55,10 @@ public class DefaultSensorDescriptor implements SensorDescriptor {
return Arrays.asList(properties);
}

public boolean isGlobal() {
return global;
}

@Override
public DefaultSensorDescriptor name(String name) {
this.name = name;
@@ -99,4 +104,10 @@ public class DefaultSensorDescriptor implements SensorDescriptor {
return this;
}

@Override
public SensorDescriptor global() {
this.global = true;
return this;
}

}

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

@@ -74,8 +74,10 @@ public class DefaultFileSystemTest {
public void add_languages() {
assertThat(fs.languages()).isEmpty();

fs.addLanguages("java", "php", "cobol");
assertThat(fs.languages()).containsOnly("cobol", "java", "php");
fs.add(new TestInputFileBuilder("foo", "src/Foo.php").setLanguage("php").build());
fs.add(new TestInputFileBuilder("foo", "src/Bar.java").setLanguage("java").build());

assertThat(fs.languages()).containsOnly("java", "php");
}

@Test

+ 20
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerExtensionDictionnary.java View File

@@ -26,6 +26,7 @@ import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

@@ -78,6 +79,25 @@ public class ScannerExtensionDictionnary {
return result;
}

public Collection<org.sonar.api.batch.Sensor> selectSensors(@Nullable DefaultInputModule module, boolean global) {
List<org.sonar.api.batch.Sensor> result = getFilteredExtensions(org.sonar.api.batch.Sensor.class, module, null);

Iterator<org.sonar.api.batch.Sensor> iterator = result.iterator();
while (iterator.hasNext()) {
org.sonar.api.batch.Sensor sensor = iterator.next();
if (sensor instanceof SensorWrapper) {
if (global != ((SensorWrapper) sensor).isGlobal()) {
iterator.remove();
}
} else if (global) {
// only old sensors are not wrapped, and old sensors are never global -> exclude
iterator.remove();
}
}

return sort(result);
}

private static Phase.Name evaluatePhase(Object extension) {
Object extensionToEvaluate;
if (extension instanceof SensorWrapper) {

+ 2
- 2
sonar-scanner-engine/src/main/java/org/sonar/scanner/cpd/deprecated/DeprecatedCpdBlockIndexerSensor.java View File

@@ -52,7 +52,8 @@ public class DeprecatedCpdBlockIndexerSensor implements Sensor {

@Override
public void describe(SensorDescriptor descriptor) {
descriptor.name("CPD Block Indexer");
descriptor.name("CPD Block Indexer")
.global();
}

@VisibleForTesting
@@ -65,7 +66,6 @@ public class DeprecatedCpdBlockIndexerSensor implements Sensor {

@Override
public void execute(SensorContext context) {

for (String language : fs.languages()) {
CpdBlockIndexer blockIndexer = getBlockIndexer(language);
if (!blockIndexer.isLanguageSupported(language)) {

+ 39
- 9
sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/SensorsExecutor.java View File

@@ -20,6 +20,9 @@
package org.sonar.scanner.phases;

import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.sonar.api.batch.ScannerSide;
import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SensorContext;
@@ -27,29 +30,56 @@ import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.resources.Project;
import org.sonar.scanner.bootstrap.ScannerExtensionDictionnary;
import org.sonar.scanner.events.EventBus;
import java.util.Collection;
import org.sonar.scanner.sensor.SensorStrategy;

@ScannerSide
public class SensorsExecutor {
private final EventBus eventBus;
private final DefaultInputModule module;
private final ScannerExtensionDictionnary selector;
private final DefaultInputModule module;
private final EventBus eventBus;
private final SensorStrategy strategy;
private final boolean isRoot;

public SensorsExecutor(ScannerExtensionDictionnary selector, DefaultInputModule module, EventBus eventBus) {
public SensorsExecutor(ScannerExtensionDictionnary selector, DefaultInputModule module, EventBus eventBus, SensorStrategy strategy) {
this.selector = selector;
this.eventBus = eventBus;
this.module = module;
this.eventBus = eventBus;
this.strategy = strategy;
this.isRoot = module.definition().getParent() == null;
}

public void execute(SensorContext context) {
Collection<Sensor> sensors = selector.select(Sensor.class, module, true, null);
eventBus.fireEvent(new SensorsPhaseEvent(Lists.newArrayList(sensors), true));
Collection<Sensor> perModuleSensors = selector.selectSensors(module, false);
Collection<Sensor> globalSensors;
if (isRoot) {
boolean orig = strategy.isGlobal();
strategy.setGlobal(true);
globalSensors = selector.selectSensors(module, true);
strategy.setGlobal(orig);
} else {
globalSensors = Collections.emptyList();
}

Collection<Sensor> allSensors = new ArrayList<>(perModuleSensors);
allSensors.addAll(globalSensors);
eventBus.fireEvent(new SensorsPhaseEvent(Lists.newArrayList(allSensors), true));

execute(context, perModuleSensors);

if (isRoot) {
boolean orig = strategy.isGlobal();
strategy.setGlobal(true);
execute(context, globalSensors);
strategy.setGlobal(orig);
}

eventBus.fireEvent(new SensorsPhaseEvent(Lists.newArrayList(allSensors), false));
}

private void execute(SensorContext context, Collection<Sensor> sensors) {
for (Sensor sensor : sensors) {
executeSensor(context, sensor);
}

eventBus.fireEvent(new SensorsPhaseEvent(Lists.newArrayList(sensors), false));
}

private void executeSensor(SensorContext context, Sensor sensor) {

+ 3
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleScanContainer.java View File

@@ -70,6 +70,7 @@ import org.sonar.scanner.scan.filesystem.StatusDetectionFactory;
import org.sonar.scanner.scan.report.IssuesReports;
import org.sonar.scanner.sensor.DefaultSensorStorage;
import org.sonar.scanner.sensor.SensorOptimizer;
import org.sonar.scanner.sensor.SensorStrategy;
import org.sonar.scanner.sensor.coverage.CoverageExclusions;
import org.sonar.scanner.source.HighlightableBuilder;
import org.sonar.scanner.source.SymbolizableBuilder;
@@ -137,6 +138,8 @@ public class ModuleScanContainer extends ComponentContainer {
IssueFilters.class,
CoverageExclusions.class,

SensorStrategy.class,

// rules
new RulesProfileProvider(),
CheckFactory.class,

+ 1
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java View File

@@ -245,6 +245,7 @@ public class ProjectScanContainer extends ComponentContainer {

LOG.debug("Start recursive analysis of project modules");
scanRecursively(tree, tree.root());

if (analysisMode.isMediumTest()) {
getComponentByType(ScanTaskObservers.class).notifyEndOfScanTask();
}

+ 68
- 10
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputComponentStore.java View File

@@ -19,14 +19,19 @@
*/
package org.sonar.scanner.scan.filesystem;

import com.google.common.base.Preconditions;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Table;
import com.google.common.collect.TreeBasedTable;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import java.util.SortedSet;
import java.util.TreeSet;
import javax.annotation.CheckForNull;

import org.sonar.api.batch.ScannerSide;
import org.sonar.api.batch.fs.InputComponent;
import org.sonar.api.batch.fs.InputDir;
@@ -34,11 +39,10 @@ import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputModule;
import org.sonar.api.batch.fs.internal.DefaultInputDir;
import org.sonar.api.batch.fs.internal.DefaultInputFile;

import com.google.common.collect.Table;
import com.google.common.collect.TreeBasedTable;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.fs.internal.FileExtensionPredicate;
import org.sonar.api.batch.fs.internal.FilenamePredicate;
import org.sonar.api.scan.filesystem.PathResolver;

/**
* Store of all files and dirs. This cache is shared amongst all project modules. Inclusion and
@@ -47,7 +51,12 @@ import org.sonar.api.batch.fs.internal.FilenamePredicate;
@ScannerSide
public class InputComponentStore {

private final PathResolver pathResolver;
private final SortedSet<String> globalLanguagesCache = new TreeSet<>();
private final Map<String, SortedSet<String>> languagesCache = new HashMap<>();
private final Map<String, InputFile> globalInputFileCache = new HashMap<>();
private final Table<String, String, InputFile> inputFileCache = TreeBasedTable.create();
private final Map<String, InputDir> globalInputDirCache = new HashMap<>();
private final Table<String, String, InputDir> inputDirCache = TreeBasedTable.create();
private final Map<String, InputModule> inputModuleCache = new HashMap<>();
private final Map<String, InputComponent> inputComponents = new HashMap<>();
@@ -55,6 +64,10 @@ public class InputComponentStore {
private final SetMultimap<String, InputFile> filesByExtensionCache = LinkedHashMultimap.create();
private InputModule root;

public InputComponentStore(PathResolver pathResolver) {
this.pathResolver = pathResolver;
}

public Collection<InputComponent> all() {
return inputComponents.values();
}
@@ -77,10 +90,6 @@ public class InputComponentStore {
return inputComponents.get(key);
}

public void setRoot(InputModule root) {
this.root = root;
}

@CheckForNull
public InputModule root() {
return root;
@@ -114,38 +123,79 @@ public class InputComponentStore {

public InputComponentStore put(InputFile inputFile) {
DefaultInputFile file = (DefaultInputFile) inputFile;
addToLanguageCache(file);
inputFileCache.put(file.moduleKey(), inputFile.relativePath(), inputFile);
globalInputFileCache.put(getProjectRelativePath(file), inputFile);
inputComponents.put(inputFile.key(), inputFile);
filesByNameCache.put(FilenamePredicate.getFilename(inputFile), inputFile);
filesByExtensionCache.put(FileExtensionPredicate.getExtension(inputFile), inputFile);
return this;
}

private void addToLanguageCache(DefaultInputFile inputFile) {
String language = inputFile.language();
if (language != null) {
globalLanguagesCache.add(language);
languagesCache.computeIfAbsent(inputFile.moduleKey(), k -> new TreeSet<>()).add(language);
}
}

public InputComponentStore put(InputDir inputDir) {
DefaultInputDir dir = (DefaultInputDir) inputDir;
inputDirCache.put(dir.moduleKey(), inputDir.relativePath(), inputDir);
globalInputDirCache.put(getProjectRelativePath(dir), inputDir);
inputComponents.put(inputDir.key(), inputDir);
return this;
}

private String getProjectRelativePath(DefaultInputFile file) {
return pathResolver.relativePath(getProjectBaseDir(), file.path());
}

private String getProjectRelativePath(DefaultInputDir dir) {
return pathResolver.relativePath(getProjectBaseDir(), dir.path());
}

private Path getProjectBaseDir() {
return ((DefaultInputModule) root).definition().getBaseDir().toPath();
}

@CheckForNull
public InputFile getFile(String moduleKey, String relativePath) {
return inputFileCache.get(moduleKey, relativePath);
}

@CheckForNull
public InputFile getFile(String relativePath) {
return globalInputFileCache.get(relativePath);
}

@CheckForNull
public InputDir getDir(String moduleKey, String relativePath) {
return inputDirCache.get(moduleKey, relativePath);
}

@CheckForNull
public InputDir getDir(String relativePath) {
return globalInputDirCache.get(relativePath);
}

@CheckForNull
public InputModule getModule(String moduleKey) {
return inputModuleCache.get(moduleKey);
}

public void put(InputModule inputModule) {
public void put(DefaultInputModule inputModule) {
Preconditions.checkState(!inputComponents.containsKey(inputModule.key()), "Module '%s' already indexed", inputModule.key());
Preconditions.checkState(!inputModuleCache.containsKey(inputModule.key()), "Module '%s' already indexed", inputModule.key());
inputComponents.put(inputModule.key(), inputModule);
inputModuleCache.put(inputModule.key(), inputModule);
if (inputModule.definition().getParent() == null) {
if (root != null) {
throw new IllegalStateException("Root module already indexed: '" + root.key() + "', '" + inputModule.key() + "'");
}
root = inputModule;
}
}

public Iterable<InputFile> getFilesByName(String filename) {
@@ -155,4 +205,12 @@ public class InputComponentStore {
public Iterable<InputFile> getFilesByExtension(String extension) {
return filesByExtensionCache.get(extension);
}

public SortedSet<String> getLanguages() {
return globalLanguagesCache;
}

public SortedSet<String> getLanguages(String moduleKey) {
return languagesCache.getOrDefault(moduleKey, Collections.emptySortedSet());
}
}

+ 29
- 4
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStore.java View File

@@ -19,36 +19,61 @@
*/
package org.sonar.scanner.scan.filesystem;

import java.util.SortedSet;
import org.sonar.api.batch.ScannerSide;
import org.sonar.api.batch.fs.InputDir;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputModule;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.scanner.sensor.SensorStrategy;

@ScannerSide
public class ModuleInputComponentStore extends DefaultFileSystem.Cache {

private final String moduleKey;
private final InputComponentStore inputComponentStore;
private final SensorStrategy strategy;

public ModuleInputComponentStore(InputModule module, InputComponentStore inputComponentStore) {
public ModuleInputComponentStore(InputModule module, InputComponentStore inputComponentStore, SensorStrategy strategy) {
this.moduleKey = module.key();
this.inputComponentStore = inputComponentStore;
this.strategy = strategy;
}

@Override
public Iterable<InputFile> inputFiles() {
return inputComponentStore.filesByModule(moduleKey);
if (strategy.isGlobal()) {
return inputComponentStore.allFiles();
} else {
return inputComponentStore.filesByModule(moduleKey);
}
}

@Override
public InputFile inputFile(String relativePath) {
return inputComponentStore.getFile(moduleKey, relativePath);
if (strategy.isGlobal()) {
return inputComponentStore.getFile(relativePath);
} else {
return inputComponentStore.getFile(moduleKey, relativePath);
}
}

@Override
public InputDir inputDir(String relativePath) {
return inputComponentStore.getDir(moduleKey, relativePath);
if (strategy.isGlobal()) {
return inputComponentStore.getDir(relativePath);
} else {
return inputComponentStore.getDir(moduleKey, relativePath);
}
}

@Override
public SortedSet<String> languages() {
if (strategy.isGlobal()) {
return inputComponentStore.getLanguages();
} else {
return inputComponentStore.getLanguages(moduleKey);
}
}

@Override

+ 38
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/SensorStrategy.java View File

@@ -0,0 +1,38 @@
/*
* SonarQube
* Copyright (C) 2009-2017 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.scanner.sensor;

/**
* A shared, mutable object in the module container.
* It's used during the execution of sensors to decide whether
* sensors should be executed once for the entire project, or per-module.
*/
public class SensorStrategy {

private boolean global = false;

public boolean isGlobal() {
return global;
}

public void setGlobal(boolean global) {
this.global = global;
}
}

+ 4
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/SensorWrapper.java View File

@@ -61,4 +61,8 @@ public class SensorWrapper implements org.sonar.api.batch.Sensor {
return wrappedSensor.getClass().getName();
}
}

public boolean isGlobal() {
return descriptor.isGlobal();
}
}

+ 2
- 1
sonar-scanner-engine/src/main/java/org/sonar/scanner/source/CodeColorizerSensor.java View File

@@ -42,7 +42,8 @@ public final class CodeColorizerSensor implements Sensor {

@Override
public void describe(SensorDescriptor descriptor) {
descriptor.name("Code Colorizer Sensor");
descriptor.name("Code Colorizer Sensor")
.global();
}

@Override

+ 2
- 1
sonar-scanner-engine/src/main/java/org/sonar/scanner/source/ZeroCoverageSensor.java View File

@@ -70,7 +70,8 @@ public final class ZeroCoverageSensor implements Sensor {

@Override
public void describe(SensorDescriptor descriptor) {
descriptor.name("Zero Coverage Sensor");
descriptor.name("Zero Coverage Sensor")
.global();
}

@Override

+ 52
- 6
sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerExtensionDictionnaryTest.java View File

@@ -36,13 +36,13 @@ import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.postjob.PostJobContext;
import org.sonar.api.batch.sensor.SensorDescriptor;
import org.sonar.api.resources.Project;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.scanner.bootstrap.ScannerExtensionDictionnary;
import org.sonar.scanner.bootstrap.ExtensionMatcher;
import org.sonar.scanner.postjob.PostJobOptimizer;
import org.sonar.scanner.sensor.DefaultSensorContext;
import org.sonar.scanner.sensor.SensorOptimizer;
import org.sonar.scanner.sensor.SensorWrapper;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
@@ -301,10 +301,7 @@ public class ScannerExtensionDictionnaryTest {
ScannerExtensionDictionnary selector = newSelector(analyze, post, pre);
List extensions = Lists.newArrayList(selector.select(BatchExtension.class, null, true, null));

assertThat(extensions).hasSize(3);
assertThat(extensions.get(0)).isEqualTo(pre);
assertThat(extensions.get(1)).isEqualTo(analyze);
assertThat(extensions.get(2)).isEqualTo(post);
assertThat(extensions).containsExactly(pre, analyze, post);
}

@Test
@@ -321,6 +318,30 @@ public class ScannerExtensionDictionnaryTest {
assertThat(extensions.get(2)).isEqualTo(checker);
}

@Test
public void querySensors() {
BatchExtension pre = new PreSensorSubclass();
BatchExtension analyze = new GeneratesSomething("something");
BatchExtension post = new PostSensorSubclass();

FakeSensor fakeSensor = new FakeSensor();
FakeNewSensor fakeNewSensor = new FakeNewSensor();
FakeNewGlobalSensor fakeNewGlobalSensor = new FakeNewGlobalSensor();
ScannerExtensionDictionnary selector = newSelector(fakeSensor, fakeNewSensor, fakeNewGlobalSensor);
List extensions = Lists.newArrayList(selector.selectSensors(null, false));

assertThat(extensions).hasSize(2);
assertThat(extensions).contains(fakeSensor);
extensions.remove(fakeSensor);
assertThat(extensions.get(0)).isInstanceOf(SensorWrapper.class);
assertThat(((SensorWrapper) extensions.get(0)).wrappedSensor()).isEqualTo(fakeNewSensor);

extensions = Lists.newArrayList(selector.selectSensors(null, true));

assertThat(extensions.get(0)).isInstanceOf(SensorWrapper.class);
assertThat(((SensorWrapper) extensions.get(0)).wrappedSensor()).isEqualTo(fakeNewGlobalSensor);
}

class FakeSensor implements Sensor {

public void analyse(Project project, SensorContext context) {
@@ -332,6 +353,31 @@ public class ScannerExtensionDictionnaryTest {
}
}

class FakeNewSensor implements org.sonar.api.batch.sensor.Sensor {

@Override
public void describe(SensorDescriptor descriptor) {
}

@Override
public void execute(org.sonar.api.batch.sensor.SensorContext context) {
}

}

class FakeNewGlobalSensor implements org.sonar.api.batch.sensor.Sensor {

@Override
public void describe(SensorDescriptor descriptor) {
descriptor.global();
}

@Override
public void execute(org.sonar.api.batch.sensor.SensorContext context) {
}

}

class MethodDependentOf implements BatchExtension {
private Object dep;


+ 3
- 3
sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdExecutorTest.java View File

@@ -32,10 +32,10 @@ import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.config.MapSettings;
import org.sonar.api.config.Settings;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
import org.sonar.core.util.CloseableIterator;
@@ -86,11 +86,11 @@ public class CpdExecutorTest {
publisher = mock(ReportPublisher.class);
when(publisher.getWriter()).thenReturn(new ScannerReportWriter(outputDir));
index = new SonarCpdBlockIndex(publisher, settings);
componentStore = new InputComponentStore();
componentStore = new InputComponentStore(new PathResolver());
executor = new CpdExecutor(settings, index, publisher, componentStore);
reader = new ScannerReportReader(outputDir);

componentStore.put(new DefaultInputModule("foo"));
componentStore.put(TestInputFileBuilder.newDefaultInputModule("foo", baseDir));

batchComponent1 = createComponent("src/Foo.php", 5);
batchComponent2 = createComponent("src/Foo2.php", 5);

+ 14
- 4
sonar-scanner-engine/src/test/java/org/sonar/scanner/postjob/DefaultPostJobContextTest.java View File

@@ -19,15 +19,19 @@
*/
package org.sonar.scanner.postjob;

import java.io.IOException;
import java.util.Arrays;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.AnalysisMode;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.batch.postjob.issue.PostJobIssue;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.config.Settings;
import org.sonar.api.config.MapSettings;
import org.sonar.api.config.Settings;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.scanner.issue.IssueCache;
import org.sonar.scanner.issue.tracking.TrackedIssue;
import org.sonar.scanner.scan.filesystem.InputComponentStore;
@@ -38,6 +42,9 @@ import static org.mockito.Mockito.when;

public class DefaultPostJobContextTest {

@Rule
public TemporaryFolder temp = new TemporaryFolder();

private IssueCache issueCache;
private InputComponentStore componentStore;
private DefaultPostJobContext context;
@@ -47,14 +54,14 @@ public class DefaultPostJobContextTest {
@Before
public void prepare() {
issueCache = mock(IssueCache.class);
componentStore = new InputComponentStore();
componentStore = new InputComponentStore(new PathResolver());
settings = new MapSettings();
analysisMode = mock(AnalysisMode.class);
context = new DefaultPostJobContext(settings, issueCache, componentStore, analysisMode);
}

@Test
public void testIssues() {
public void testIssues() throws IOException {
when(analysisMode.isIssues()).thenReturn(true);

assertThat(context.settings()).isSameAs(settings);
@@ -78,7 +85,10 @@ public class DefaultPostJobContextTest {
assertThat(issue.severity()).isEqualTo(Severity.BLOCKER);
assertThat(issue.inputComponent()).isNull();

componentStore.put(new TestInputFileBuilder("foo", "src/Foo.php").build());
String moduleKey = "foo";
componentStore.put(TestInputFileBuilder.newDefaultInputModule("foo", temp.newFolder()));

componentStore.put(new TestInputFileBuilder(moduleKey, "src/Foo.php").build());
assertThat(issue.inputComponent()).isNotNull();

}

+ 7
- 6
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/CoveragePublisherTest.java View File

@@ -20,15 +20,16 @@
package org.sonar.scanner.report;

import java.io.File;
import java.io.IOException;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.core.util.CloseableIterator;
import org.sonar.scanner.protocol.output.ScannerReport.LineCoverage;
import org.sonar.scanner.protocol.output.ScannerReportReader;
@@ -49,14 +50,14 @@ public class CoveragePublisherTest {
private MeasureCache measureCache;
private CoveragePublisher publisher;

private InputComponentStore componentCache;
private DefaultInputFile inputFile;

@Before
public void prepare() {
inputFile = new TestInputFileBuilder("foo", "src/Foo.php").setLines(5).build();
componentCache = new InputComponentStore();
componentCache.put(new DefaultInputModule("foo"));
public void prepare() throws IOException {
String moduleKey = "foo";
inputFile = new TestInputFileBuilder(moduleKey, "src/Foo.php").setLines(5).build();
InputComponentStore componentCache = new InputComponentStore(new PathResolver());
componentCache.put(TestInputFileBuilder.newDefaultInputModule(moduleKey, temp.newFolder()));
componentCache.put(inputFile);

measureCache = mock(MeasureCache.class);

+ 8
- 7
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MeasuresPublisherTest.java View File

@@ -33,6 +33,7 @@ import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.core.util.CloseableIterator;
import org.sonar.scanner.deprecated.test.TestPlanBuilder;
import org.sonar.scanner.protocol.output.ScannerReport;
@@ -58,18 +59,18 @@ public class MeasuresPublisherTest {
private MeasureCache measureCache;
private MeasuresPublisher publisher;

private InputComponentStore componentCache;
private File outputDir;
private ScannerReportWriter writer;
private DefaultInputFile inputFile;
private DefaultInputModule InputModule;
private DefaultInputModule inputModule;

@Before
public void prepare() throws IOException {
InputModule = new DefaultInputModule("foo");
inputFile = new TestInputFileBuilder("foo", "src/Foo.php").setPublish(true).build();
componentCache = new InputComponentStore();
componentCache.put(InputModule);
String moduleKey = "foo";
inputModule = TestInputFileBuilder.newDefaultInputModule(moduleKey, temp.newFolder());
inputFile = new TestInputFileBuilder(moduleKey, "src/Foo.php").setPublish(true).build();
InputComponentStore componentCache = new InputComponentStore(new PathResolver());
componentCache.put(inputModule);
componentCache.put(inputFile);
measureCache = mock(MeasureCache.class);
when(measureCache.byComponentKey(anyString())).thenReturn(Collections.<DefaultMeasure<?>>emptyList());
@@ -90,7 +91,7 @@ public class MeasuresPublisherTest {
publisher.publish(writer);
ScannerReportReader reader = new ScannerReportReader(outputDir);

assertThat(reader.readComponentMeasures(InputModule.batchId())).hasSize(0);
assertThat(reader.readComponentMeasures(inputModule.batchId())).hasSize(0);
try (CloseableIterator<ScannerReport.Measure> componentMeasures = reader.readComponentMeasures(inputFile.batchId())) {
assertThat(componentMeasures).hasSize(2);
}

+ 7
- 6
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/SourcePublisherTest.java View File

@@ -28,10 +28,9 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.scanner.protocol.output.ScannerReportWriter;
import org.sonar.scanner.report.SourcePublisher;
import org.sonar.scanner.scan.filesystem.InputComponentStore;

import static org.assertj.core.api.Assertions.assertThat;
@@ -44,20 +43,22 @@ public class SourcePublisherTest {
private File sourceFile;
private ScannerReportWriter writer;
private DefaultInputFile inputFile;
private InputComponentStore componentStore;

@Before
public void prepare() throws IOException {
File baseDir = temp.newFolder();
sourceFile = new File(baseDir, "src/Foo.php");
inputFile = new TestInputFileBuilder("foo", "src/Foo.php")
String moduleKey = "foo";
inputFile = new TestInputFileBuilder(moduleKey, "src/Foo.php")
.setLines(5)
.setModuleBaseDir(baseDir.toPath())
.setCharset(StandardCharsets.ISO_8859_1)
.build();
componentStore = new InputComponentStore();
componentStore.put(new DefaultInputModule("foo"));

InputComponentStore componentStore = new InputComponentStore(new PathResolver());
componentStore.put(TestInputFileBuilder.newDefaultInputModule(moduleKey, baseDir));
componentStore.put(inputFile);

publisher = new SourcePublisher(componentStore);
File outputDir = temp.newFolder();
writer = new ScannerReportWriter(outputDir);

+ 8
- 3
sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/QProfileVerifierTest.java View File

@@ -26,6 +26,7 @@ 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.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.config.Settings;
import org.sonar.api.config.MapSettings;
import org.sonar.api.utils.MessageException;
@@ -58,7 +59,9 @@ public class QProfileVerifierTest {

@Test
public void should_log_all_used_profiles() {
fs.addLanguages("java", "cobol");
fs.add(new TestInputFileBuilder("foo", "src/Bar.java").setLanguage("java").build());
fs.add(new TestInputFileBuilder("foo", "src/Baz.cbl").setLanguage("cobol").build());

QProfileVerifier profileLogger = new QProfileVerifier(settings, fs, profiles);
Logger logger = mock(Logger.class);
profileLogger.execute(logger);
@@ -69,7 +72,8 @@ public class QProfileVerifierTest {

@Test
public void should_fail_if_default_profile_not_used() {
fs.addLanguages("java", "cobol");
fs.add(new TestInputFileBuilder("foo", "src/Bar.java").setLanguage("java").build());

settings.setProperty("sonar.profile", "Unknown");

QProfileVerifier profileLogger = new QProfileVerifier(settings, fs, profiles);
@@ -92,7 +96,8 @@ public class QProfileVerifierTest {

@Test
public void should_not_fail_if_default_profile_used_at_least_once() {
fs.addLanguages("java", "cobol");
fs.add(new TestInputFileBuilder("foo", "src/Bar.java").setLanguage("java").build());

settings.setProperty("sonar.profile", "My Java profile");

QProfileVerifier profileLogger = new QProfileVerifier(settings, fs, profiles);

+ 6
- 5
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleIndexerTest.java View File

@@ -19,17 +19,18 @@
*/
package org.sonar.scanner.scan;

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

import org.junit.Before;
import org.junit.Test;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.InputModule;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.scanner.scan.filesystem.BatchIdGenerator;
import org.sonar.scanner.scan.filesystem.InputComponentStore;

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

public class ModuleIndexerTest {
private ModuleIndexer indexer;
private DefaultComponentTree tree;
@@ -40,7 +41,7 @@ public class ModuleIndexerTest {
@Before
public void setUp() {
reactor = mock(ImmutableProjectReactor.class);
componentStore = new InputComponentStore();
componentStore = new InputComponentStore(new PathResolver());
tree = new DefaultComponentTree();
moduleHierarchy = new DefaultInputModuleHierarchy();
indexer = new ModuleIndexer(reactor, tree, componentStore, new BatchIdGenerator(), moduleHierarchy);

+ 26
- 13
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputComponentStoreTest.java View File

@@ -19,12 +19,10 @@
*/
package org.sonar.scanner.scan.filesystem;

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

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -33,7 +31,11 @@ import org.sonar.api.batch.fs.InputFile.Status;
import org.sonar.api.batch.fs.InputFile.Type;
import org.sonar.api.batch.fs.InputPath;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.scan.filesystem.PathResolver;

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

public class InputComponentStoreTest {
@Rule
@@ -41,13 +43,24 @@ public class InputComponentStoreTest {

@Test
public void should_add_input_file() throws Exception {
InputComponentStore cache = new InputComponentStore();
DefaultInputFile fooFile = new TestInputFileBuilder("struts", "src/main/java/Foo.java")
.setModuleBaseDir(temp.newFolder().toPath())
InputComponentStore cache = new InputComponentStore(new PathResolver());

String rootModuleKey = "struts";
File rootBaseDir = temp.newFolder();
DefaultInputModule rootModule = TestInputFileBuilder.newDefaultInputModule(rootModuleKey, rootBaseDir);
cache.put(rootModule);

String subModuleKey = "struts-core";
DefaultInputModule subModule = TestInputFileBuilder.newDefaultInputModule(subModuleKey, temp.newFolder());
rootModule.definition().addSubProject(subModule.definition());
cache.put(subModule);

DefaultInputFile fooFile = new TestInputFileBuilder(rootModuleKey, "src/main/java/Foo.java")
.setModuleBaseDir(rootBaseDir.toPath())
.setPublish(true)
.build();
cache.put(fooFile);
cache.put(new TestInputFileBuilder("struts-core", "src/main/java/Bar.java")
cache.put(new TestInputFileBuilder(subModuleKey, "src/main/java/Bar.java")
.setLanguage("bla")
.setPublish(false)
.setType(Type.MAIN)
@@ -57,12 +70,12 @@ public class InputComponentStoreTest {
.setModuleBaseDir(temp.newFolder().toPath())
.build());

DefaultInputFile loadedFile = (DefaultInputFile) cache.getFile("struts-core", "src/main/java/Bar.java");
DefaultInputFile loadedFile = (DefaultInputFile) cache.getFile(subModuleKey, "src/main/java/Bar.java");
assertThat(loadedFile.relativePath()).isEqualTo("src/main/java/Bar.java");
assertThat(loadedFile.charset()).isEqualTo(StandardCharsets.UTF_8);

assertThat(cache.filesByModule("struts")).hasSize(1);
assertThat(cache.filesByModule("struts-core")).hasSize(1);
assertThat(cache.filesByModule(rootModuleKey)).hasSize(1);
assertThat(cache.filesByModule(subModuleKey)).hasSize(1);
assertThat(cache.allFiles()).hasSize(2);
for (InputPath inputPath : cache.allFiles()) {
assertThat(inputPath.relativePath()).startsWith("src/main/java/");
@@ -75,9 +88,9 @@ public class InputComponentStoreTest {
cache.remove(fooFile);
assertThat(cache.allFiles()).hasSize(1);

cache.removeModule("struts");
assertThat(cache.filesByModule("struts")).hasSize(0);
assertThat(cache.filesByModule("struts-core")).hasSize(1);
cache.removeModule(rootModuleKey);
assertThat(cache.filesByModule(rootModuleKey)).hasSize(0);
assertThat(cache.filesByModule(subModuleKey)).hasSize(1);
assertThat(cache.allFiles()).hasSize(1);
}


+ 28
- 8
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java View File

@@ -20,21 +20,38 @@
package org.sonar.scanner.scan.filesystem;

import java.io.IOException;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputModule;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.scanner.sensor.SensorStrategy;

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

public class ModuleInputComponentStoreTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();

private InputComponentStore componentStore;

private final String moduleKey = "dummy key";

@Before
public void setUp() throws IOException {
componentStore = new InputComponentStore(new PathResolver());
componentStore.put(TestInputFileBuilder.newDefaultInputModule(moduleKey, temp.newFolder()));
}

@Test
public void should_cache_files_by_filename() throws IOException {
ModuleInputComponentStore store = new ModuleInputComponentStore(mock(InputModule.class), new InputComponentStore());
ModuleInputComponentStore store = newModuleInputComponentStore();

String filename = "some name";
String moduleKey = "dummy key";
InputFile inputFile1 = new TestInputFileBuilder(moduleKey, "some/path/" + filename).build();
store.doAdd(inputFile1);

@@ -49,9 +66,8 @@ public class ModuleInputComponentStoreTest {

@Test
public void should_cache_files_by_extension() throws IOException {
ModuleInputComponentStore store = new ModuleInputComponentStore(mock(InputModule.class), new InputComponentStore());
ModuleInputComponentStore store = newModuleInputComponentStore();

String moduleKey = "dummy key";
InputFile inputFile1 = new TestInputFileBuilder(moduleKey, "some/path/Program.java").build();
store.doAdd(inputFile1);

@@ -66,11 +82,11 @@ public class ModuleInputComponentStoreTest {

@Test
public void should_not_cache_duplicates() throws IOException {
ModuleInputComponentStore store = new ModuleInputComponentStore(mock(InputModule.class), new InputComponentStore());
ModuleInputComponentStore store = newModuleInputComponentStore();

String ext = "java";
String filename = "Program." + ext;
InputFile inputFile = new TestInputFileBuilder("dummy key", "some/path/" + filename).build();
InputFile inputFile = new TestInputFileBuilder(moduleKey, "some/path/" + filename).build();
store.doAdd(inputFile);
store.doAdd(inputFile);
store.doAdd(inputFile);
@@ -81,14 +97,18 @@ public class ModuleInputComponentStoreTest {

@Test
public void should_get_empty_iterable_on_cache_miss() {
ModuleInputComponentStore store = new ModuleInputComponentStore(mock(InputModule.class), new InputComponentStore());
ModuleInputComponentStore store = newModuleInputComponentStore();

String ext = "java";
String filename = "Program." + ext;
InputFile inputFile = new TestInputFileBuilder("dummy key", "some/path/" + filename).build();
InputFile inputFile = new TestInputFileBuilder(moduleKey, "some/path/" + filename).build();
store.doAdd(inputFile);

assertThat(store.getFilesByName("nonexistent")).isEmpty();
assertThat(store.getFilesByExtension("nonexistent")).isEmpty();
}

private ModuleInputComponentStore newModuleInputComponentStore() {
return new ModuleInputComponentStore(mock(InputModule.class), componentStore, mock(SensorStrategy.class));
}
}

Loading…
Cancel
Save