diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2015-11-04 17:43:02 +0100 |
---|---|---|
committer | Julien HENRY <julien.henry@sonarsource.com> | 2015-11-09 08:41:26 +0100 |
commit | d24589f13f3e6712be21bacd14b670f5eacdfe8b (patch) | |
tree | 69b005107ffe32d8f9289ba90913b210b69ff2b1 /sonar-batch | |
parent | eb5fd4fe77eb1b82b3aa5e1c3474d85ac39ee9ce (diff) | |
download | sonarqube-d24589f13f3e6712be21bacd14b670f5eacdfe8b.tar.gz sonarqube-d24589f13f3e6712be21bacd14b670f5eacdfe8b.zip |
SONAR-6989 Feed the file duplication index in the batch report
Diffstat (limited to 'sonar-batch')
16 files changed, 237 insertions, 332 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/analysis/DefaultAnalysisMode.java b/sonar-batch/src/main/java/org/sonar/batch/analysis/DefaultAnalysisMode.java index 31784aa1e80..34df18afaa8 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/analysis/DefaultAnalysisMode.java +++ b/sonar-batch/src/main/java/org/sonar/batch/analysis/DefaultAnalysisMode.java @@ -19,16 +19,15 @@ */ package org.sonar.batch.analysis; -import org.sonar.batch.bootstrap.AbstractAnalysisMode; - -import org.sonar.batch.mediumtest.FakePluginInstaller; -import org.sonar.batch.bootstrap.GlobalProperties; +import java.util.Map; +import javax.annotation.CheckForNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.CoreProperties; import org.sonar.api.batch.AnalysisMode; - -import java.util.Map; +import org.sonar.batch.bootstrap.AbstractAnalysisMode; +import org.sonar.batch.bootstrap.GlobalProperties; +import org.sonar.batch.mediumtest.FakePluginInstaller; /** * @since 4.0 @@ -99,6 +98,7 @@ public class DefaultAnalysisMode extends AbstractAnalysisMode implements Analysi } } + @CheckForNull private static String getPropertyWithFallback(Map<String, String> props1, Map<String, String> props2, String key) { if (props1.containsKey(key)) { return props1.get(key); diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdComponents.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdComponents.java index e2c5555d4e2..ffac2cba012 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdComponents.java +++ b/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdComponents.java @@ -20,11 +20,8 @@ package org.sonar.batch.cpd; import com.google.common.collect.ImmutableList; - import java.util.List; -import org.sonar.batch.cpd.index.IndexFactory; - public final class CpdComponents { private CpdComponents() { @@ -34,7 +31,6 @@ public final class CpdComponents { return ImmutableList.of( CpdSensor.class, CpdMappings.class, - IndexFactory.class, JavaCpdEngine.class, DefaultCpdEngine.class); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/DefaultCpdEngine.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/DefaultCpdEngine.java index 93fc1726b46..a63b04f0006 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/cpd/DefaultCpdEngine.java +++ b/sonar-batch/src/main/java/org/sonar/batch/cpd/DefaultCpdEngine.java @@ -23,6 +23,13 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.CoreProperties; @@ -33,24 +40,13 @@ import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.config.Settings; -import org.sonar.api.resources.Project; -import org.sonar.api.utils.SonarException; -import org.sonar.batch.cpd.index.IndexFactory; import org.sonar.batch.cpd.index.SonarDuplicationsIndex; +import org.sonar.batch.index.BatchComponentCache; +import org.sonar.batch.report.ReportPublisher; import org.sonar.duplications.block.Block; import org.sonar.duplications.index.CloneGroup; import org.sonar.duplications.internal.pmd.TokenizerBridge; -import javax.annotation.Nullable; - -import java.util.Collection; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - public class DefaultCpdEngine extends CpdEngine { private static final Logger LOG = LoggerFactory.getLogger(DefaultCpdEngine.class); @@ -60,22 +56,18 @@ public class DefaultCpdEngine extends CpdEngine { */ private static final int TIMEOUT = 5 * 60; - private final IndexFactory indexFactory; private final CpdMappings mappings; private final FileSystem fs; private final Settings settings; - private final Project project; + private final ReportPublisher publisher; + private final BatchComponentCache batchComponentCache; - public DefaultCpdEngine(@Nullable Project project, IndexFactory indexFactory, CpdMappings mappings, FileSystem fs, Settings settings) { - this.project = project; - this.indexFactory = indexFactory; + public DefaultCpdEngine(CpdMappings mappings, FileSystem fs, Settings settings, ReportPublisher publisher, BatchComponentCache batchComponentCache) { this.mappings = mappings; this.fs = fs; this.settings = settings; - } - - public DefaultCpdEngine(IndexFactory indexFactory, CpdMappings mappings, FileSystem fs, Settings settings) { - this(null, indexFactory, mappings, fs, settings); + this.publisher = publisher; + this.batchComponentCache = batchComponentCache; } @Override @@ -97,14 +89,13 @@ public class DefaultCpdEngine extends CpdEngine { List<InputFile> sourceFiles = Lists.newArrayList(fs.inputFiles(p.and( p.hasType(InputFile.Type.MAIN), p.hasLanguage(languageKey), - p.doesNotMatchPathPatterns(cpdExclusions) - ))); + p.doesNotMatchPathPatterns(cpdExclusions)))); if (sourceFiles.isEmpty()) { return; } // Create index - SonarDuplicationsIndex index = indexFactory.create(project, languageKey); + SonarDuplicationsIndex index = new SonarDuplicationsIndex(publisher, batchComponentCache, settings); populateIndex(languageKey, sourceFiles, mapping, index); // Detect @@ -129,7 +120,7 @@ public class DefaultCpdEngine extends CpdEngine { filtered = null; LOG.warn("Timeout during detection of duplications for " + inputFile, e); } catch (InterruptedException | ExecutionException e) { - throw new SonarException("Fail during detection of duplication for " + inputFile, e); + throw new IllegalStateException("Fail during detection of duplication for " + inputFile, e); } JavaCpdEngine.save(context, inputFile, filtered); @@ -144,8 +135,8 @@ public class DefaultCpdEngine extends CpdEngine { for (InputFile inputFile : sourceFiles) { LOG.debug("Populating index from {}", inputFile); String resourceEffectiveKey = ((DefaultInputFile) inputFile).key(); - List<Block> blocks2 = bridge.chunk(resourceEffectiveKey, inputFile.file()); - index.insert(inputFile, blocks2); + List<Block> blocks = bridge.chunk(resourceEffectiveKey, inputFile.file()); + index.insert(inputFile, blocks); } } @@ -162,7 +153,7 @@ public class DefaultCpdEngine extends CpdEngine { static int getDefaultBlockSize(String languageKey) { if ("cobol".equals(languageKey)) { return 30; - } else if ("abap".equals(languageKey) || "natur".equals(languageKey)) { + } else if ("abap".equals(languageKey)) { return 20; } else { return 10; @@ -173,9 +164,6 @@ public class DefaultCpdEngine extends CpdEngine { int getMinimumTokens(String languageKey) { int minimumTokens = settings.getInt("sonar.cpd." + languageKey + ".minimumTokens"); if (minimumTokens == 0) { - minimumTokens = settings.getInt(CoreProperties.CPD_MINIMUM_TOKENS_PROPERTY); - } - if (minimumTokens == 0) { minimumTokens = 100; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdEngine.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdEngine.java index 97059241af5..1adca4f11ca 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdEngine.java +++ b/sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdEngine.java @@ -22,6 +22,21 @@ package org.sonar.batch.cpd; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import javax.annotation.Nullable; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,10 +51,9 @@ import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication; import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; import org.sonar.api.config.Settings; import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.resources.Project; -import org.sonar.api.utils.SonarException; -import org.sonar.batch.cpd.index.IndexFactory; import org.sonar.batch.cpd.index.SonarDuplicationsIndex; +import org.sonar.batch.index.BatchComponentCache; +import org.sonar.batch.report.ReportPublisher; import org.sonar.duplications.block.Block; import org.sonar.duplications.block.BlockChunker; import org.sonar.duplications.detector.suffixtree.SuffixTreeCloneDetectionAlgorithm; @@ -52,23 +66,6 @@ import org.sonar.duplications.statement.Statement; import org.sonar.duplications.statement.StatementChunker; import org.sonar.duplications.token.TokenChunker; -import javax.annotation.Nullable; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - public class JavaCpdEngine extends CpdEngine { private static final Logger LOG = LoggerFactory.getLogger(JavaCpdEngine.class); @@ -83,20 +80,16 @@ public class JavaCpdEngine extends CpdEngine { private static final int MAX_CLONE_GROUP_PER_FILE = 100; private static final int MAX_CLONE_PART_PER_GROUP = 100; - private final IndexFactory indexFactory; private final FileSystem fs; private final Settings settings; - private final Project project; + private final ReportPublisher publisher; + private final BatchComponentCache batchComponentCache; - public JavaCpdEngine(@Nullable Project project, IndexFactory indexFactory, FileSystem fs, Settings settings) { - this.project = project; - this.indexFactory = indexFactory; + public JavaCpdEngine(FileSystem fs, Settings settings, ReportPublisher publisher, BatchComponentCache batchComponentCache) { this.fs = fs; this.settings = settings; - } - - public JavaCpdEngine(IndexFactory indexFactory, FileSystem fs, Settings settings) { - this(null, indexFactory, fs, settings); + this.publisher = publisher; + this.batchComponentCache = batchComponentCache; } @Override @@ -112,17 +105,16 @@ public class JavaCpdEngine extends CpdEngine { List<InputFile> sourceFiles = Lists.newArrayList(fs.inputFiles(p.and( p.hasType(InputFile.Type.MAIN), p.hasLanguage(languageKey), - p.doesNotMatchPathPatterns(cpdExclusions) - ))); + p.doesNotMatchPathPatterns(cpdExclusions)))); if (sourceFiles.isEmpty()) { return; } - SonarDuplicationsIndex index = createIndex(project, languageKey, sourceFiles); + SonarDuplicationsIndex index = createIndex(sourceFiles); detect(index, context, sourceFiles); } - private SonarDuplicationsIndex createIndex(@Nullable Project project, String language, Iterable<InputFile> sourceFiles) { - final SonarDuplicationsIndex index = indexFactory.create(project, language); + private SonarDuplicationsIndex createIndex(Iterable<InputFile> sourceFiles) { + final SonarDuplicationsIndex index = new SonarDuplicationsIndex(publisher, batchComponentCache, settings); TokenChunker tokenChunker = JavaTokenProducer.build(); StatementChunker statementChunker = JavaStatementBuilder.build(); @@ -139,7 +131,7 @@ public class JavaCpdEngine extends CpdEngine { reader = new InputStreamReader(new FileInputStream(inputFile.file()), fs.encoding()); statements = statementChunker.chunk(tokenChunker.chunk(reader)); } catch (FileNotFoundException e) { - throw new SonarException("Cannot find file " + inputFile.file(), e); + throw new IllegalStateException("Cannot find file " + inputFile.file(), e); } finally { IOUtils.closeQuietly(reader); } @@ -166,10 +158,8 @@ public class JavaCpdEngine extends CpdEngine { } catch (TimeoutException e) { clones = null; LOG.warn("Timeout during detection of duplications for " + inputFile, e); - } catch (InterruptedException e) { - throw new SonarException("Fail during detection of duplication for " + inputFile, e); - } catch (ExecutionException e) { - throw new SonarException("Fail during detection of duplication for " + inputFile, e); + } catch (InterruptedException | ExecutionException e) { + throw new IllegalStateException("Fail during detection of duplication for " + inputFile, e); } save(context, inputFile, clones); @@ -209,20 +199,20 @@ public class JavaCpdEngine extends CpdEngine { .forMetric(CoreMetrics.DUPLICATED_FILES) .on(inputFile) .withValue(1)) - .setFromCore() - .save(); + .setFromCore() + .save(); ((DefaultMeasure<Integer>) context.<Integer>newMeasure() .forMetric(CoreMetrics.DUPLICATED_LINES) .on(inputFile) .withValue(duplicatedLines)) - .setFromCore() - .save(); + .setFromCore() + .save(); ((DefaultMeasure<Integer>) context.<Integer>newMeasure() .forMetric(CoreMetrics.DUPLICATED_BLOCKS) .on(inputFile) .withValue(duplicatedBlocks)) - .setFromCore() - .save(); + .setFromCore() + .save(); } private static void saveDuplications(org.sonar.api.batch.sensor.SensorContext context, InputFile inputFile, Iterable<CloneGroup> duplications) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/index/IndexFactory.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/index/IndexFactory.java deleted file mode 100644 index 31a4b03ce55..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/cpd/index/IndexFactory.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.cpd.index; - -import org.sonar.batch.analysis.DefaultAnalysisMode; - -import com.google.common.annotations.VisibleForTesting; - -import javax.annotation.Nullable; - -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.sonar.api.CoreProperties; -import org.sonar.api.batch.BatchSide; -import org.sonar.api.config.Settings; -import org.sonar.api.resources.Project; - -@BatchSide -public class IndexFactory { - - private final Settings settings; - private final DefaultAnalysisMode mode; - - public IndexFactory(DefaultAnalysisMode mode, Settings settings) { - this.mode = mode; - this.settings = settings; - } - - public SonarDuplicationsIndex create(@Nullable Project project, String languageKey) { - return new SonarDuplicationsIndex(); - } - - @VisibleForTesting - boolean verifyCrossProject(@Nullable Project project, Logger logger) { - boolean crossProject = false; - - if (settings.getBoolean(CoreProperties.CPD_CROSS_PROJECT)) { - if (mode.isIssues()) { - logger.info("Cross-project analysis disabled. Not supported in issues mode."); - } else if (StringUtils.isNotBlank(settings.getString(CoreProperties.PROJECT_BRANCH_PROPERTY))) { - logger.info("Cross-project analysis disabled. Not supported on project branches."); - } else if (project == null) { - // New sensor mode - logger.info("Cross-project analysis disabled. Not supported in new sensor mode."); - } else { - logger.info("Cross-project analysis enabled"); - crossProject = true; - } - } else { - logger.info("Cross-project analysis disabled"); - } - return crossProject; - } -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/index/SonarDuplicationsIndex.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/index/SonarDuplicationsIndex.java index ab583d672dd..51a094a869e 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/cpd/index/SonarDuplicationsIndex.java +++ b/sonar-batch/src/main/java/org/sonar/batch/cpd/index/SonarDuplicationsIndex.java @@ -19,8 +19,17 @@ */ package org.sonar.batch.cpd.index; +import com.google.common.base.Function; +import com.google.common.collect.Iterables; import java.util.Collection; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.CoreProperties; import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.config.Settings; +import org.sonar.batch.index.BatchComponentCache; +import org.sonar.batch.protocol.output.BatchReport; +import org.sonar.batch.protocol.output.BatchReport.DuplicationBlock; +import org.sonar.batch.report.ReportPublisher; import org.sonar.duplications.block.Block; import org.sonar.duplications.block.ByteArray; import org.sonar.duplications.index.AbstractCloneIndex; @@ -30,13 +39,46 @@ import org.sonar.duplications.index.PackedMemoryCloneIndex; public class SonarDuplicationsIndex extends AbstractCloneIndex { private final CloneIndex mem = new PackedMemoryCloneIndex(); + private final ReportPublisher publisher; + private final BatchComponentCache batchComponentCache; + private final Settings settings; + + public SonarDuplicationsIndex(ReportPublisher publisher, BatchComponentCache batchComponentCache, Settings settings) { + this.publisher = publisher; + this.batchComponentCache = batchComponentCache; + this.settings = settings; + } public void insert(InputFile inputFile, Collection<Block> blocks) { + if (isCrossProjectDuplicationEnabled(settings)) { + int id = batchComponentCache.get(inputFile).batchId(); + final BatchReport.DuplicationBlock.Builder builder = BatchReport.DuplicationBlock.newBuilder(); + publisher.getWriter().writeDuplicationBlocks(id, Iterables.transform(blocks, new Function<Block, BatchReport.DuplicationBlock>() { + @Override + public DuplicationBlock apply(Block input) { + builder.clear(); + builder.setStartLine(input.getStartLine()); + builder.setEndLine(input.getEndLine()); + builder.setStartTokenIndex(input.getStartUnit()); + builder.setEndTokenIndex(input.getEndUnit()); + for (int i : input.getBlockHash().toIntArray()) { + builder.addHash(i); + } + return builder.build(); + } + })); + } for (Block block : blocks) { mem.insert(block); } } + public static boolean isCrossProjectDuplicationEnabled(Settings settings) { + return settings.getBoolean(CoreProperties.CPD_CROSS_PROJECT) + // No cross project duplication for branches + && StringUtils.isBlank(settings.getString(CoreProperties.PROJECT_BRANCH_PROPERTY)); + } + public Collection<Block> getByInputFile(InputFile inputFile, String resourceKey) { return mem.getByResourceId(resourceKey); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java index 04b5724b2c3..49c7f95736b 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java +++ b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java @@ -41,10 +41,8 @@ import org.sonar.api.batch.fs.TextPointer; import org.sonar.api.batch.fs.TextRange; import org.sonar.api.batch.fs.internal.DefaultInputDir; import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.batch.sensor.duplication.Duplication; import org.sonar.api.batch.sensor.highlighting.TypeOfText; import org.sonar.api.issue.Issue; -import org.sonar.batch.duplication.DuplicationCache; import org.sonar.batch.issue.IssueCache; import org.sonar.batch.protocol.output.BatchReport; import org.sonar.batch.protocol.output.BatchReport.Component; @@ -63,7 +61,6 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver { private static final Logger LOG = LoggerFactory.getLogger(TaskResult.class); private List<Issue> issues = new ArrayList<>(); - private Map<String, List<Duplication>> duplications = new HashMap<>(); private Map<String, InputFile> inputFiles = new HashMap<>(); private Map<String, Component> reportComponents = new HashMap<>(); private Map<String, InputDir> inputDirs = new HashMap<>(); @@ -86,7 +83,6 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver { storeFs(container); - storeDuplication(container); } private void storeReportComponents(int componentRef, String parentModuleKey, @Nullable String branch) { @@ -106,13 +102,6 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver { return reader; } - private void storeDuplication(ProjectScanContainer container) { - DuplicationCache duplicationCache = container.getComponentByType(DuplicationCache.class); - for (String effectiveKey : duplicationCache.componentKeys()) { - duplications.put(effectiveKey, Lists.<Duplication>newArrayList(duplicationCache.byComponent(effectiveKey))); - } - } - private void storeFs(ProjectScanContainer container) { InputPathCache inputFileCache = container.getComponentByType(InputPathCache.class); for (InputFile inputPath : inputFileCache.allFiles()) { @@ -127,6 +116,10 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver { return issues; } + public Component getReportComponent(String key) { + return reportComponents.get(key); + } + public List<BatchReport.Issue> issuesFor(InputPath inputPath) { List<BatchReport.Issue> result = Lists.newArrayList(); int ref = reportComponents.get(key(inputPath)).getRef(); @@ -162,10 +155,6 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver { return inputDirs.get(relativePath); } - public List<Duplication> duplicationsFor(InputFile inputFile) { - return duplications.get(((DefaultInputFile) inputFile).key()); - } - public Map<String, List<BatchReport.Measure>> allMeasures() { Map<String, List<BatchReport.Measure>> result = new HashMap<>(); for (Map.Entry<String, Component> component : reportComponents.entrySet()) { @@ -226,6 +215,32 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver { return Collections.emptyList(); } + public List<BatchReport.Duplication> duplicationsFor(InputFile file) { + List<BatchReport.Duplication> result = new ArrayList<>(); + int ref = reportComponents.get(((DefaultInputFile) file).key()).getRef(); + try (CloseableIterator<BatchReport.Duplication> it = getReportReader().readComponentDuplications(ref)) { + while (it.hasNext()) { + result.add(it.next()); + } + } catch (Exception e) { + throw new IllegalStateException(e); + } + return result; + } + + public List<BatchReport.DuplicationBlock> duplicationBlocksFor(InputFile file) { + List<BatchReport.DuplicationBlock> result = new ArrayList<>(); + int ref = reportComponents.get(((DefaultInputFile) file).key()).getRef(); + try (CloseableIterator<BatchReport.DuplicationBlock> it = getReportReader().readComponentDuplicationBlocks(ref)) { + while (it.hasNext()) { + result.add(it.next()); + } + } catch (Exception e) { + throw new IllegalStateException(e); + } + return result; + } + @CheckForNull public BatchReport.Coverage coverageFor(InputFile file, int line) { int ref = reportComponents.get(((DefaultInputFile) file).key()).getRef(); diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/DuplicationsPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/DuplicationsPublisher.java index 6cf132a9f6e..068cb1c10e4 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/report/DuplicationsPublisher.java +++ b/sonar-batch/src/main/java/org/sonar/batch/report/DuplicationsPublisher.java @@ -81,7 +81,8 @@ public class DuplicationsPublisher implements ReportPublisherStep { if (sameProjectComponent != null) { blockBuilder.setOtherFileRef(sameProjectComponent.batchId()); } else { - blockBuilder.setOtherFileKey(componentKey); + // Should never happens + throw new IllegalStateException("No cross project duplication supported on batch side: " + componentKey); } } dupBuilder.addDuplicate(blockBuilder diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/MetadataPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/MetadataPublisher.java index 52e98b53d81..9c1d2faca6d 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/report/MetadataPublisher.java +++ b/sonar-batch/src/main/java/org/sonar/batch/report/MetadataPublisher.java @@ -21,7 +21,9 @@ package org.sonar.batch.report; import org.sonar.api.CoreProperties; import org.sonar.api.batch.bootstrap.ProjectDefinition; +import org.sonar.api.config.Settings; import org.sonar.api.resources.Project; +import org.sonar.batch.cpd.index.SonarDuplicationsIndex; import org.sonar.batch.index.BatchComponent; import org.sonar.batch.index.BatchComponentCache; import org.sonar.batch.protocol.output.BatchReport; @@ -32,10 +34,12 @@ public class MetadataPublisher implements ReportPublisherStep { private final BatchComponentCache componentCache; private final ImmutableProjectReactor reactor; + private final Settings settings; - public MetadataPublisher(BatchComponentCache componentCache, ImmutableProjectReactor reactor) { + public MetadataPublisher(BatchComponentCache componentCache, ImmutableProjectReactor reactor, Settings settings) { this.componentCache = componentCache; this.reactor = reactor; + this.settings = settings; } @Override @@ -46,6 +50,7 @@ public class MetadataPublisher implements ReportPublisherStep { .setAnalysisDate(((Project) rootProject.resource()).getAnalysisDate().getTime()) // Here we want key without branch .setProjectKey(root.getKey()) + .setCrossProjectDuplicationActivated(SonarDuplicationsIndex.isCrossProjectDuplicationEnabled(settings)) .setRootComponentRef(rootProject.batchId()); String branch = root.properties().get(CoreProperties.PROJECT_BRANCH_PROPERTY); if (branch != null) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java index 0c6a9d67fa2..bcb38b4958a 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java +++ b/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java @@ -95,18 +95,18 @@ public class DefaultSensorStorage implements SensorStorage { private final ModuleIssues moduleIssues; private final CoverageExclusions coverageExclusions; private final DuplicationCache duplicationCache; - private final BatchComponentCache resourceCache; + private final BatchComponentCache componentCache; private final ReportPublisher reportPublisher; private final MeasureCache measureCache; public DefaultSensorStorage(MetricFinder metricFinder, ModuleIssues moduleIssues, Settings settings, FileSystem fs, ActiveRules activeRules, DuplicationCache duplicationCache, - CoverageExclusions coverageExclusions, BatchComponentCache resourceCache, ReportPublisher reportPublisher, MeasureCache measureCache) { + CoverageExclusions coverageExclusions, BatchComponentCache componentCache, ReportPublisher reportPublisher, MeasureCache measureCache) { this.metricFinder = metricFinder; this.moduleIssues = moduleIssues; this.coverageExclusions = coverageExclusions; this.duplicationCache = duplicationCache; - this.resourceCache = resourceCache; + this.componentCache = componentCache; this.reportPublisher = reportPublisher; this.measureCache = measureCache; } @@ -127,7 +127,7 @@ public class DefaultSensorStorage implements SensorStorage { setValueAccordingToMetricType(newMeasure, m, measureToSave); measureToSave.setFromCore(measure.isFromCore()); InputComponent inputComponent = newMeasure.inputComponent(); - Resource resource = resourceCache.get(inputComponent).resource(); + Resource resource = componentCache.get(inputComponent).resource(); if (coverageExclusions.accept(resource, measureToSave)) { saveMeasure(resource, measureToSave); } @@ -183,7 +183,7 @@ public class DefaultSensorStorage implements SensorStorage { } private File getFile(InputFile file) { - BatchComponent r = resourceCache.get(file); + BatchComponent r = componentCache.get(file); if (r == null) { throw new IllegalStateException("Provided input file is not indexed"); } @@ -199,13 +199,13 @@ public class DefaultSensorStorage implements SensorStorage { public void store(DefaultHighlighting highlighting) { BatchReportWriter writer = reportPublisher.getWriter(); DefaultInputFile inputFile = (DefaultInputFile) highlighting.inputFile(); - writer.writeComponentSyntaxHighlighting(resourceCache.get(inputFile).batchId(), + writer.writeComponentSyntaxHighlighting(componentCache.get(inputFile).batchId(), Iterables.transform(highlighting.getSyntaxHighlightingRuleSet(), new BuildSyntaxHighlighting())); } public void store(DefaultInputFile inputFile, Map<Symbol, Set<TextRange>> referencesBySymbol) { BatchReportWriter writer = reportPublisher.getWriter(); - writer.writeComponentSymbols(resourceCache.get(inputFile).batchId(), + writer.writeComponentSymbols(componentCache.get(inputFile).batchId(), Iterables.transform(referencesBySymbol.entrySet(), new Function<Map.Entry<Symbol, Set<TextRange>>, BatchReport.Symbol>() { private BatchReport.Symbol.Builder builder = BatchReport.Symbol.newBuilder(); private BatchReport.TextRange.Builder rangeBuilder = BatchReport.TextRange.newBuilder(); diff --git a/sonar-batch/src/test/java/org/sonar/batch/cpd/CpdSensorTest.java b/sonar-batch/src/test/java/org/sonar/batch/cpd/CpdSensorTest.java index a99d356c87b..5c5adb3a4c2 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/cpd/CpdSensorTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/cpd/CpdSensorTest.java @@ -19,6 +19,7 @@ */ package org.sonar.batch.cpd; +import java.io.IOException; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -27,12 +28,8 @@ import org.sonar.api.batch.fs.internal.DefaultFileSystem; import org.sonar.api.config.PropertyDefinitions; import org.sonar.api.config.Settings; import org.sonar.api.resources.Java; -import org.sonar.batch.cpd.index.IndexFactory; - -import java.io.IOException; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; public class CpdSensorTest { @@ -46,9 +43,8 @@ public class CpdSensorTest { @Before public void setUp() throws IOException { - IndexFactory indexFactory = mock(IndexFactory.class); - sonarEngine = new JavaCpdEngine(indexFactory, null, null); - sonarBridgeEngine = new DefaultCpdEngine(indexFactory, new CpdMappings(), null, null); + sonarEngine = new JavaCpdEngine(null, null, null, null); + sonarBridgeEngine = new DefaultCpdEngine(new CpdMappings(), null, null, null, null); settings = new Settings(new PropertyDefinitions(CpdComponents.class)); DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder().toPath()); diff --git a/sonar-batch/src/test/java/org/sonar/batch/cpd/DefaultCpdEngineTest.java b/sonar-batch/src/test/java/org/sonar/batch/cpd/DefaultCpdEngineTest.java index fb2a632e9c9..427c62a1e4c 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/cpd/DefaultCpdEngineTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/cpd/DefaultCpdEngineTest.java @@ -23,7 +23,6 @@ import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.sonar.api.config.Settings; -import org.sonar.api.resources.Project; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.anyString; @@ -40,7 +39,7 @@ public class DefaultCpdEngineTest { @Before public void init() { settings = new Settings(); - engine = new DefaultCpdEngine(null, null, null, settings); + engine = new DefaultCpdEngine(null, null, settings, null, null); } @Test @@ -61,7 +60,6 @@ public class DefaultCpdEngineTest { @Test public void shouldReturnDefaultBlockSize() { assertThat(DefaultCpdEngine.getDefaultBlockSize("cobol")).isEqualTo(30); - assertThat(DefaultCpdEngine.getDefaultBlockSize("natur")).isEqualTo(20); assertThat(DefaultCpdEngine.getDefaultBlockSize("abap")).isEqualTo(20); assertThat(DefaultCpdEngine.getDefaultBlockSize("other")).isEqualTo(10); } @@ -85,13 +83,6 @@ public class DefaultCpdEngineTest { } @Test - public void generalMinimumTokens() { - settings.setProperty("sonar.cpd.minimumTokens", 33); - - assertThat(engine.getMinimumTokens("java")).isEqualTo(33); - } - - @Test public void minimumTokensByLanguage() { settings.setProperty("sonar.cpd.java.minimumTokens", "42"); settings.setProperty("sonar.cpd.php.minimumTokens", "33"); @@ -102,7 +93,4 @@ public class DefaultCpdEngineTest { assertThat(engine.getMinimumTokens("php")).isEqualTo(33); } - private static Project newProject(String key) { - return new Project(key).setAnalysisType(Project.AnalysisType.DYNAMIC); - } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/cpd/index/IndexFactoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/cpd/index/IndexFactoryTest.java deleted file mode 100644 index f33f40b6cba..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/cpd/index/IndexFactoryTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.cpd.index; - -import org.sonar.batch.analysis.DefaultAnalysisMode; - -import org.junit.Before; -import org.junit.Test; -import org.slf4j.Logger; -import org.sonar.api.CoreProperties; -import org.sonar.api.config.Settings; -import org.sonar.api.resources.Project; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class IndexFactoryTest { - - Project project; - Settings settings; - IndexFactory factory; - Logger logger; - private DefaultAnalysisMode analysisMode; - - @Before - public void setUp() { - project = new Project("foo"); - settings = new Settings(); - analysisMode = mock(DefaultAnalysisMode.class); - factory = new IndexFactory(analysisMode, settings); - logger = mock(Logger.class); - } - - @Test - public void crossProjectEnabled() { - settings.setProperty(CoreProperties.CPD_CROSS_PROJECT, "true"); - assertThat(factory.verifyCrossProject(project, logger)).isTrue(); - verify(logger).info("Cross-project analysis enabled"); - } - - @Test - public void noCrossProjectWithBranch() { - settings.setProperty(CoreProperties.CPD_CROSS_PROJECT, "true"); - settings.setProperty(CoreProperties.PROJECT_BRANCH_PROPERTY, "branch"); - assertThat(factory.verifyCrossProject(project, logger)).isFalse(); - verify(logger).info("Cross-project analysis disabled. Not supported on project branches."); - } - - @Test - public void cross_project_should_be_disabled_on_issues_mode() { - when(analysisMode.isIssues()).thenReturn(true); - settings.setProperty(CoreProperties.CPD_CROSS_PROJECT, "true"); - assertThat(factory.verifyCrossProject(project, logger)).isFalse(); - verify(logger).info("Cross-project analysis disabled. Not supported in issues mode."); - } - - @Test - public void crossProjectDisabled() { - settings.setProperty(CoreProperties.CPD_CROSS_PROJECT, "false"); - assertThat(factory.verifyCrossProject(project, logger)).isFalse(); - verify(logger).info("Cross-project analysis disabled"); - } - -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/cpd/CpdMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/cpd/CpdMediumTest.java index 03b171ae31e..7a0c260e4f7 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/cpd/CpdMediumTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/cpd/CpdMediumTest.java @@ -34,10 +34,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.sensor.duplication.Duplication; import org.sonar.api.measures.CoreMetrics; import org.sonar.batch.mediumtest.BatchMediumTester; import org.sonar.batch.mediumtest.TaskResult; +import org.sonar.batch.protocol.output.BatchReport.DuplicationBlock; import org.sonar.batch.protocol.output.BatchReport.Measure; import org.sonar.xoo.XooPlugin; @@ -112,28 +112,70 @@ public class CpdMediumTest { InputFile inputFile1 = result.inputFile("src/sample1.xoo"); InputFile inputFile2 = result.inputFile("src/sample2.xoo"); + // One clone group on each file - List<Duplication> duplicationGroupsFile1 = result.duplicationsFor(inputFile1); + List<org.sonar.batch.protocol.output.BatchReport.Duplication> duplicationGroupsFile1 = result.duplicationsFor(inputFile1); assertThat(duplicationGroupsFile1).hasSize(1); - Duplication cloneGroupFile1 = duplicationGroupsFile1.get(0); - assertThat(cloneGroupFile1.duplicates()).hasSize(1); - assertThat(cloneGroupFile1.originBlock().startLine()).isEqualTo(1); - assertThat(cloneGroupFile1.originBlock().length()).isEqualTo(17); - assertThat(cloneGroupFile1.originBlock().resourceKey()).isEqualTo(((DefaultInputFile) inputFile1).key()); - assertThat(cloneGroupFile1.duplicates()).hasSize(1); - assertThat(cloneGroupFile1.duplicates().get(0).resourceKey()).isEqualTo(((DefaultInputFile) inputFile2).key()); + org.sonar.batch.protocol.output.BatchReport.Duplication cloneGroupFile1 = duplicationGroupsFile1.get(0); + assertThat(cloneGroupFile1.getOriginPosition().getStartLine()).isEqualTo(1); + assertThat(cloneGroupFile1.getOriginPosition().getEndLine()).isEqualTo(17); + assertThat(cloneGroupFile1.getDuplicateList()).hasSize(1); + assertThat(cloneGroupFile1.getDuplicate(0).getOtherFileRef()).isEqualTo(result.getReportComponent(((DefaultInputFile) inputFile2).key()).getRef()); - List<Duplication> duplicationGroupsFile2 = result.duplicationsFor(inputFile2); + List<org.sonar.batch.protocol.output.BatchReport.Duplication> duplicationGroupsFile2 = result.duplicationsFor(inputFile2); assertThat(duplicationGroupsFile2).hasSize(1); - Duplication cloneGroupFile2 = duplicationGroupsFile2.get(0); - assertThat(cloneGroupFile2.duplicates()).hasSize(1); - assertThat(cloneGroupFile2.originBlock().startLine()).isEqualTo(1); - assertThat(cloneGroupFile2.originBlock().length()).isEqualTo(17); - assertThat(cloneGroupFile2.originBlock().resourceKey()).isEqualTo(((DefaultInputFile) inputFile2).key()); - assertThat(cloneGroupFile2.duplicates()).hasSize(1); - assertThat(cloneGroupFile2.duplicates().get(0).resourceKey()).isEqualTo(((DefaultInputFile) inputFile1).key()); + org.sonar.batch.protocol.output.BatchReport.Duplication cloneGroupFile2 = duplicationGroupsFile2.get(0); + assertThat(cloneGroupFile2.getOriginPosition().getStartLine()).isEqualTo(1); + assertThat(cloneGroupFile2.getOriginPosition().getEndLine()).isEqualTo(17); + assertThat(cloneGroupFile2.getDuplicateList()).hasSize(1); + assertThat(cloneGroupFile2.getDuplicate(0).getOtherFileRef()).isEqualTo(result.getReportComponent(((DefaultInputFile) inputFile1).key()).getRef()); + + assertThat(result.duplicationBlocksFor(inputFile1)).isEmpty(); + } + + @Test + public void enableCrossProjectDuplication() throws IOException { + File srcDir = new File(baseDir, "src"); + srcDir.mkdir(); + + String duplicatedStuff = "Sample xoo\ncontent\nfoo\nbar\ntoto\ntiti\nfoo"; + + File xooFile1 = new File(srcDir, "sample1.xoo"); + FileUtils.write(xooFile1, duplicatedStuff); + + TaskResult result = tester.newTask() + .properties(builder + .put("sonar.sources", "src") + .put("sonar.cpd.xoo.minimumTokens", "1") + .put("sonar.cpd.xoo.minimumLines", "5") + .put("sonar.verbose", "true") + .put("sonar.cpd.cross_project", "true") + .build()) + .start(); + + InputFile inputFile1 = result.inputFile("src/sample1.xoo"); + + List<DuplicationBlock> duplicationBlocks = result.duplicationBlocksFor(inputFile1); + assertThat(duplicationBlocks).hasSize(3); + assertThat(duplicationBlocks.get(0).getStartLine()).isEqualTo(1); + assertThat(duplicationBlocks.get(0).getEndLine()).isEqualTo(5); + assertThat(duplicationBlocks.get(0).getStartTokenIndex()).isEqualTo(1); + assertThat(duplicationBlocks.get(0).getEndTokenIndex()).isEqualTo(6); + assertThat(duplicationBlocks.get(0).getHashList()).isNotEmpty(); + + assertThat(duplicationBlocks.get(1).getStartLine()).isEqualTo(2); + assertThat(duplicationBlocks.get(1).getEndLine()).isEqualTo(6); + assertThat(duplicationBlocks.get(1).getStartTokenIndex()).isEqualTo(3); + assertThat(duplicationBlocks.get(1).getEndTokenIndex()).isEqualTo(7); + assertThat(duplicationBlocks.get(0).getHashList()).isNotEmpty(); + + assertThat(duplicationBlocks.get(2).getStartLine()).isEqualTo(3); + assertThat(duplicationBlocks.get(2).getEndLine()).isEqualTo(7); + assertThat(duplicationBlocks.get(2).getStartTokenIndex()).isEqualTo(4); + assertThat(duplicationBlocks.get(2).getEndTokenIndex()).isEqualTo(8); + assertThat(duplicationBlocks.get(0).getHashList()).isNotEmpty(); } // SONAR-6000 @@ -171,11 +213,11 @@ public class CpdMediumTest { Tuple.tuple(CoreMetrics.DUPLICATED_BLOCKS_KEY, blockCount), Tuple.tuple(CoreMetrics.DUPLICATED_LINES_KEY, blockCount)); - List<Duplication> duplicationGroups = result.duplicationsFor(result.inputFile("src/sample.xoo")); + List<org.sonar.batch.protocol.output.BatchReport.Duplication> duplicationGroups = result.duplicationsFor(result.inputFile("src/sample.xoo")); assertThat(duplicationGroups).hasSize(1); - Duplication cloneGroup = duplicationGroups.get(0); - assertThat(cloneGroup.duplicates()).hasSize(100); + org.sonar.batch.protocol.output.BatchReport.Duplication cloneGroup = duplicationGroups.get(0); + assertThat(cloneGroup.getDuplicateList()).hasSize(100); } @Test @@ -205,16 +247,15 @@ public class CpdMediumTest { InputFile inputFile = result.inputFile("src/sample.xoo"); // One clone group - List<Duplication> duplicationGroups = result.duplicationsFor(inputFile); + List<org.sonar.batch.protocol.output.BatchReport.Duplication> duplicationGroups = result.duplicationsFor(inputFile); assertThat(duplicationGroups).hasSize(1); - Duplication cloneGroup = duplicationGroups.get(0); - assertThat(cloneGroup.duplicates()).hasSize(1); - assertThat(cloneGroup.originBlock().startLine()).isEqualTo(1); - assertThat(cloneGroup.originBlock().length()).isEqualTo(2); - assertThat(cloneGroup.duplicates()).hasSize(1); - assertThat(cloneGroup.duplicates().get(0).startLine()).isEqualTo(5); - assertThat(cloneGroup.duplicates().get(0).length()).isEqualTo(2); + org.sonar.batch.protocol.output.BatchReport.Duplication cloneGroup = duplicationGroups.get(0); + assertThat(cloneGroup.getOriginPosition().getStartLine()).isEqualTo(1); + assertThat(cloneGroup.getOriginPosition().getEndLine()).isEqualTo(2); + assertThat(cloneGroup.getDuplicateList()).hasSize(1); + assertThat(cloneGroup.getDuplicate(0).getRange().getStartLine()).isEqualTo(5); + assertThat(cloneGroup.getDuplicate(0).getRange().getEndLine()).isEqualTo(6); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/DuplicationsPublisherTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/DuplicationsPublisherTest.java index 731bad05db4..b57c18df8e2 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/report/DuplicationsPublisherTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/report/DuplicationsPublisherTest.java @@ -73,11 +73,8 @@ public class DuplicationsPublisherTest { .isDuplicatedBy("foo:src/Foo.php", 20, 50); DefaultDuplication dup2 = new DefaultDuplication() .setOriginBlock(new Duplication.Block("foo:src/Foo.php", 11, 10)) - .isDuplicatedBy("another", 20, 50); - DefaultDuplication dup3 = new DefaultDuplication() - .setOriginBlock(new Duplication.Block("foo:src/Foo.php", 11, 10)) .isDuplicatedBy("foo:src/Foo2.php", 20, 50); - when(duplicationCache.byComponent("foo:src/Foo.php")).thenReturn(Arrays.asList(dup1, dup2, dup3)); + when(duplicationCache.byComponent("foo:src/Foo.php")).thenReturn(Arrays.asList(dup1, dup2)); File outputDir = temp.newFolder(); BatchReportWriter writer = new BatchReportWriter(outputDir); @@ -91,7 +88,6 @@ public class DuplicationsPublisherTest { org.sonar.batch.protocol.output.BatchReport.Duplication savedDup1 = componentDuplications.next(); assertThat(savedDup1.getOriginPosition().getStartLine()).isEqualTo(1); assertThat(savedDup1.getOriginPosition().getEndLine()).isEqualTo(10); - assertThat(savedDup1.getDuplicate(0).hasOtherFileKey()).isFalse(); assertThat(savedDup1.getDuplicate(0).hasOtherFileRef()).isFalse(); assertThat(savedDup1.getDuplicate(0).getRange().getStartLine()).isEqualTo(20); assertThat(savedDup1.getDuplicate(0).getRange().getEndLine()).isEqualTo(50); @@ -99,19 +95,10 @@ public class DuplicationsPublisherTest { org.sonar.batch.protocol.output.BatchReport.Duplication savedDup2 = componentDuplications.next(); assertThat(savedDup2.getOriginPosition().getStartLine()).isEqualTo(11); assertThat(savedDup2.getOriginPosition().getEndLine()).isEqualTo(20); - assertThat(savedDup2.getDuplicate(0).getOtherFileKey()).isEqualTo("another"); - assertThat(savedDup2.getDuplicate(0).hasOtherFileRef()).isFalse(); + assertThat(savedDup2.getDuplicate(0).getOtherFileRef()).isEqualTo(3); assertThat(savedDup2.getDuplicate(0).getRange().getStartLine()).isEqualTo(20); assertThat(savedDup2.getDuplicate(0).getRange().getEndLine()).isEqualTo(50); - org.sonar.batch.protocol.output.BatchReport.Duplication savedDup3 = componentDuplications.next(); - assertThat(savedDup3.getOriginPosition().getStartLine()).isEqualTo(11); - assertThat(savedDup3.getOriginPosition().getEndLine()).isEqualTo(20); - assertThat(savedDup3.getDuplicate(0).hasOtherFileKey()).isFalse(); - assertThat(savedDup3.getDuplicate(0).getOtherFileRef()).isEqualTo(3); - assertThat(savedDup3.getDuplicate(0).getRange().getStartLine()).isEqualTo(20); - assertThat(savedDup3.getDuplicate(0).getRange().getEndLine()).isEqualTo(50); - assertThat(componentDuplications.hasNext()).isFalse(); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/MetadataPublisherTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/MetadataPublisherTest.java index eab392c374f..eb93a5661c5 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/report/MetadataPublisherTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/report/MetadataPublisherTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.sonar.api.CoreProperties; import org.sonar.api.batch.bootstrap.ProjectDefinition; +import org.sonar.api.config.Settings; import org.sonar.api.resources.Project; import org.sonar.batch.index.BatchComponentCache; import org.sonar.batch.protocol.output.BatchReport; @@ -41,10 +42,10 @@ public class MetadataPublisherTest { @Rule public TemporaryFolder temp = new TemporaryFolder(); - ProjectDefinition projectDef; - Project project; - - MetadataPublisher underTest; + private ProjectDefinition projectDef; + private Project project; + private MetadataPublisher underTest; + private Settings settings; @Before public void prepare() { @@ -54,11 +55,13 @@ public class MetadataPublisherTest { org.sonar.api.resources.Resource sampleFile = org.sonar.api.resources.File.create("src/Foo.php").setEffectiveKey("foo:src/Foo.php"); componentCache.add(project, null); componentCache.add(sampleFile, project); - underTest = new MetadataPublisher(componentCache, new ImmutableProjectReactor(projectDef)); + settings = new Settings(); + underTest = new MetadataPublisher(componentCache, new ImmutableProjectReactor(projectDef), settings); } @Test public void write_metadata() throws Exception { + settings.setProperty(CoreProperties.CPD_CROSS_PROJECT, "true"); File outputDir = temp.newFolder(); BatchReportWriter writer = new BatchReportWriter(outputDir); @@ -68,10 +71,14 @@ public class MetadataPublisherTest { BatchReport.Metadata metadata = reader.readMetadata(); assertThat(metadata.getAnalysisDate()).isEqualTo(1234567L); assertThat(metadata.getProjectKey()).isEqualTo("foo"); + assertThat(metadata.getProjectKey()).isEqualTo("foo"); + assertThat(metadata.getCrossProjectDuplicationActivated()).isTrue(); } @Test public void write_project_branch() throws Exception { + settings.setProperty(CoreProperties.CPD_CROSS_PROJECT, "true"); + settings.setProperty(CoreProperties.PROJECT_BRANCH_PROPERTY, "myBranch"); projectDef.properties().put(CoreProperties.PROJECT_BRANCH_PROPERTY, "myBranch"); project.setKey("foo:myBranch"); project.setEffectiveKey("foo:myBranch"); @@ -86,6 +93,8 @@ public class MetadataPublisherTest { assertThat(metadata.getAnalysisDate()).isEqualTo(1234567L); assertThat(metadata.getProjectKey()).isEqualTo("foo"); assertThat(metadata.getBranch()).isEqualTo("myBranch"); + // Cross project duplication disabled on branches + assertThat(metadata.getCrossProjectDuplicationActivated()).isFalse(); } } |