From 95764997034f8f7e3e8afda432bc87591d857a0b Mon Sep 17 00:00:00 2001
From: Duarte Meneses
Date: Thu, 20 Jun 2019 15:05:37 -0500
Subject: [PATCH] SONAR-11458 Log analysis warning when cross-project
duplication detection is used
---
.../task/projectanalysis/analysis/Branch.java | 2 +-
.../duplication/Duplication.java | 66 +++++++------------
.../IntegrateCrossProjectDuplications.java | 45 +++++++------
...rossProjectDuplicationsRepositoryStep.java | 28 ++++----
.../DuplicationRepositoryRule.java | 2 +-
.../duplication/DuplicationTest.java | 15 ++---
...IntegrateCrossProjectDuplicationsTest.java | 32 +++++----
7 files changed, 90 insertions(+), 100 deletions(-)
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/analysis/Branch.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/analysis/Branch.java
index 22c0702dd15..c4a022f0724 100644
--- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/analysis/Branch.java
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/analysis/Branch.java
@@ -49,7 +49,7 @@ public interface Branch extends ComponentKeyGenerator {
String getMergeBranchUuid();
/**
- * Whether the cross-project duplication tracker must be enabled
+ * Whether the cross-project duplication tracker can be enabled
* or not.
*/
boolean supportsCrossProjectCpd();
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/duplication/Duplication.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/duplication/Duplication.java
index c858b2d68fc..8f129042d84 100644
--- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/duplication/Duplication.java
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/duplication/Duplication.java
@@ -19,41 +19,49 @@
*/
package org.sonar.ce.task.projectanalysis.duplication;
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Ordering;
import java.util.Comparator;
+import java.util.List;
import java.util.Objects;
import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.function.Function;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.FluentIterable.from;
import static java.util.Objects.requireNonNull;
@Immutable
public final class Duplication {
- private static final Ordering DUPLICATE_ORDERING = Ordering.from(DuplicateComparatorByType.INSTANCE)
- .compound(Ordering.natural().onResultOf(DuplicateToFileKey.INSTANCE))
- .compound(Ordering.natural().onResultOf(DuplicateToTextBlock.INSTANCE));
+ private static final Comparator DUPLICATE_COMPARATOR = DuplicateComparatorByType.INSTANCE
+ .thenComparing(DuplicateToFileKey.INSTANCE).thenComparing(DuplicateToTextBlock.INSTANCE);
private final TextBlock original;
private final SortedSet duplicates;
/**
- * @throws NullPointerException if {@code original} is {@code null} or {@code duplicates} is {@code null} or {@code duplicates} contains {@code null}
+ * @throws NullPointerException if {@code original} is {@code null} or {@code duplicates} is {@code null} or {@code duplicates} contains {@code null}
* @throws IllegalArgumentException if {@code duplicates} is empty
* @throws IllegalArgumentException if {@code duplicates} contains a {@link InnerDuplicate} with {@code original}
*/
- public Duplication(final TextBlock original, final Iterable duplicates) {
+ public Duplication(TextBlock original, List duplicates) {
this.original = requireNonNull(original, "original TextBlock can not be null");
- this.duplicates = from(requireNonNull(duplicates, "duplicates can not be null"))
- .filter(FailOnNullDuplicate.INSTANCE)
- .filter(new EnsureInnerDuplicateIsNotOriginalTextBlock(original))
- .toSortedSet(DUPLICATE_ORDERING);
- checkArgument(!this.duplicates.isEmpty(), "duplicates can not be empty");
+ validateDuplicates(original, duplicates);
+ this.duplicates = new TreeSet<>(DUPLICATE_COMPARATOR);
+ this.duplicates.addAll(duplicates);
+ }
+
+ private static void validateDuplicates(TextBlock original, List duplicates) {
+ requireNonNull(duplicates, "duplicates can not be null");
+ checkArgument(!duplicates.isEmpty(), "duplicates can not be empty");
+
+ for (Duplicate dup : duplicates) {
+ requireNonNull(dup, "duplicates can not contain null");
+ if (dup instanceof InnerDuplicate) {
+ checkArgument(!original.equals(dup.getTextBlock()), "TextBlock of an InnerDuplicate can not be the original TextBlock");
+ }
+ }
}
/**
@@ -67,8 +75,8 @@ public final class Duplication {
* The duplicates of the original, sorted by inner duplicates, then project duplicates, then cross-project duplicates.
* For each category of duplicate, they are sorted by:
*
- * - file key (unless it's an InnerDuplicate)
- * - then by TextBlocks by start line and in case of same line, by shortest first
+ * - file key (unless it's an InnerDuplicate)
+ * - then by TextBlocks by start line and in case of same line, by shortest first
*
The returned set can not be empty and no inner duplicate can contain the original {@link TextBlock}.
*/
@@ -101,16 +109,6 @@ public final class Duplication {
'}';
}
- private enum FailOnNullDuplicate implements Predicate {
- INSTANCE;
-
- @Override
- public boolean apply(@Nullable Duplicate input) {
- requireNonNull(input, "duplicates can not contain null");
- return true;
- }
- }
-
private enum DuplicateComparatorByType implements Comparator {
INSTANCE;
@@ -143,22 +141,6 @@ public final class Duplication {
}
}
- private static class EnsureInnerDuplicateIsNotOriginalTextBlock implements Predicate {
- private final TextBlock original;
-
- public EnsureInnerDuplicateIsNotOriginalTextBlock(TextBlock original) {
- this.original = original;
- }
-
- @Override
- public boolean apply(@Nullable Duplicate input) {
- if (input instanceof InnerDuplicate) {
- checkArgument(!original.equals(input.getTextBlock()), "TextBlock of an InnerDuplicate can not be the original TextBlock");
- }
- return true;
- }
- }
-
private enum DuplicateToFileKey implements Function {
INSTANCE;
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/duplication/IntegrateCrossProjectDuplications.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/duplication/IntegrateCrossProjectDuplications.java
index 7cc2e8d5d17..c362762edc6 100644
--- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/duplication/IntegrateCrossProjectDuplications.java
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/duplication/IntegrateCrossProjectDuplications.java
@@ -19,18 +19,20 @@
*/
package org.sonar.ce.task.projectanalysis.duplication;
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.sonar.api.CoreProperties;
import org.sonar.api.config.Configuration;
+import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.sonar.ce.task.log.CeTaskMessages;
import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.duplications.block.Block;
import org.sonar.duplications.detector.suffixtree.SuffixTreeCloneDetectionAlgorithm;
@@ -39,16 +41,15 @@ import org.sonar.duplications.index.CloneIndex;
import org.sonar.duplications.index.ClonePart;
import org.sonar.duplications.index.PackedMemoryCloneIndex;
-import static com.google.common.collect.FluentIterable.from;
-
/**
* Transform a list of duplication blocks into clone groups, then add these clone groups into the duplication repository.
*/
public class IntegrateCrossProjectDuplications {
private static final Logger LOGGER = Loggers.get(IntegrateCrossProjectDuplications.class);
-
private static final String JAVA_KEY = "java";
+ private static final String DEPRECATED_WARNING = "This analysis uses the deprecated cross-project duplication feature.";
+ private static final String DEPRECATED_WARNING_DASHBOARD = "This project uses the deprecated cross-project duplication feature.";
private static final int MAX_CLONE_GROUP_PER_FILE = 100;
private static final int MAX_CLONE_PART_PER_GROUP = 100;
@@ -58,11 +59,12 @@ public class IntegrateCrossProjectDuplications {
private Map numberOfUnitsByLanguage = new HashMap<>();
- public IntegrateCrossProjectDuplications(Configuration config, DuplicationRepository duplicationRepository) {
+ public IntegrateCrossProjectDuplications(Configuration config, DuplicationRepository duplicationRepository, CeTaskMessages ceTaskMessages, System2 system) {
this.config = config;
this.duplicationRepository = duplicationRepository;
if (config.getBoolean(CoreProperties.CPD_CROSS_PROJECT).orElse(false)) {
- LOGGER.warn("This analysis uses the deprecated cross-project duplication feature.");
+ LOGGER.warn(DEPRECATED_WARNING);
+ ceTaskMessages.add(new CeTaskMessages.Message(DEPRECATED_WARNING_DASHBOARD, system.now()));
}
}
@@ -72,7 +74,9 @@ public class IntegrateCrossProjectDuplications {
populateIndex(duplicationIndex, duplicationBlocks);
List duplications = SuffixTreeCloneDetectionAlgorithm.detect(duplicationIndex, originBlocks);
- Iterable filtered = from(duplications).filter(getNumberOfUnitsNotLessThan(component.getFileAttributes().getLanguageKey()));
+ Iterable filtered = duplications.stream()
+ .filter(getNumberOfUnitsNotLessThan(component.getFileAttributes().getLanguageKey()))
+ .collect(Collectors.toList());
addDuplications(component, filtered);
}
@@ -96,20 +100,21 @@ public class IntegrateCrossProjectDuplications {
private void addDuplication(Component file, CloneGroup duplication) {
ClonePart originPart = duplication.getOriginPart();
- Iterable duplicates = convertClonePartsToDuplicates(file, duplication);
- if (!Iterables.isEmpty(duplicates)) {
+ List duplicates = convertClonePartsToDuplicates(file, duplication);
+ if (!duplicates.isEmpty()) {
duplicationRepository.add(
file,
new Duplication(new TextBlock(originPart.getStartLine(), originPart.getEndLine()), duplicates));
}
}
- private static Iterable convertClonePartsToDuplicates(final Component file, CloneGroup duplication) {
+ private static List convertClonePartsToDuplicates(final Component file, CloneGroup duplication) {
final ClonePart originPart = duplication.getOriginPart();
- return from(duplication.getCloneParts())
+ return duplication.getCloneParts().stream()
.filter(new DoesNotMatchSameComponentKey(originPart.getResourceId()))
.filter(new DuplicateLimiter(file, originPart))
- .transform(ClonePartToCrossProjectDuplicate.INSTANCE);
+ .map(ClonePartToCrossProjectDuplicate.INSTANCE)
+ .collect(Collectors.toList());
}
private NumberOfUnitsNotLessThan getNumberOfUnitsNotLessThan(String language) {
@@ -132,12 +137,12 @@ public class IntegrateCrossProjectDuplications {
private static class NumberOfUnitsNotLessThan implements Predicate {
private final int min;
- public NumberOfUnitsNotLessThan(int min) {
+ NumberOfUnitsNotLessThan(int min) {
this.min = min;
}
@Override
- public boolean apply(@Nonnull CloneGroup input) {
+ public boolean test(@Nonnull CloneGroup input) {
return input.getLengthInUnits() >= min;
}
}
@@ -150,7 +155,7 @@ public class IntegrateCrossProjectDuplications {
}
@Override
- public boolean apply(@Nonnull ClonePart part) {
+ public boolean test(@Nonnull ClonePart part) {
return !part.getResourceId().equals(componentKey);
}
}
@@ -160,18 +165,18 @@ public class IntegrateCrossProjectDuplications {
private final ClonePart originPart;
private int counter = 0;
- public DuplicateLimiter(Component file, ClonePart originPart) {
+ DuplicateLimiter(Component file, ClonePart originPart) {
this.file = file;
this.originPart = originPart;
}
@Override
- public boolean apply(@Nonnull ClonePart input) {
+ public boolean test(@Nonnull ClonePart input) {
if (counter == MAX_CLONE_PART_PER_GROUP) {
LOGGER.warn("Too many duplication references on file {} for block at line {}. Keeping only the first {} references.",
file.getDbKey(), originPart.getStartLine(), MAX_CLONE_PART_PER_GROUP);
}
- boolean res = counter <= MAX_CLONE_GROUP_PER_FILE;
+ boolean res = counter < MAX_CLONE_GROUP_PER_FILE;
counter++;
return res;
}
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadCrossProjectDuplicationsRepositoryStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadCrossProjectDuplicationsRepositoryStep.java
index adcfdc744bb..09d56ae2f7e 100644
--- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadCrossProjectDuplicationsRepositoryStep.java
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadCrossProjectDuplicationsRepositoryStep.java
@@ -19,9 +19,11 @@
*/
package org.sonar.ce.task.projectanalysis.step;
-import com.google.common.base.Function;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
@@ -44,12 +46,8 @@ import org.sonar.duplications.block.Block;
import org.sonar.duplications.block.ByteArray;
import org.sonar.scanner.protocol.output.ScannerReport.CpdTextBlock;
-import static com.google.common.collect.FluentIterable.from;
-import static com.google.common.collect.Lists.newArrayList;
-
/**
* Feed the duplications repository from the cross project duplication blocks computed with duplications blocks of the analysis report.
- *
* Blocks can be empty if :
* - The file is excluded from the analysis using {@link org.sonar.api.CoreProperties#CPD_EXCLUSIONS}
* - On Java, if the number of statements of the file is too small, nothing will be sent.
@@ -96,23 +94,25 @@ public class LoadCrossProjectDuplicationsRepositoryStep implements ComputationSt
@Override
public void visitFile(Component file) {
- List cpdTextBlocks;
+ List cpdTextBlocks = new ArrayList<>();
try (CloseableIterator blocksIt = reportReader.readCpdTextBlocks(file.getReportAttributes().getRef())) {
- cpdTextBlocks = newArrayList(blocksIt);
- LOGGER.trace("Found {} cpd blocks on file {}", cpdTextBlocks.size(), file.getDbKey());
- if (cpdTextBlocks.isEmpty()) {
- return;
+ while(blocksIt.hasNext()) {
+ cpdTextBlocks.add(blocksIt.next());
}
}
+ LOGGER.trace("Found {} cpd blocks on file {}", cpdTextBlocks.size(), file.getDbKey());
+ if (cpdTextBlocks.isEmpty()) {
+ return;
+ }
- Collection hashes = from(cpdTextBlocks).transform(CpdTextBlockToHash.INSTANCE).toList();
+ Collection hashes = cpdTextBlocks.stream().map(CpdTextBlockToHash.INSTANCE).collect(Collectors.toList());
List dtos = selectDuplicates(file, hashes);
if (dtos.isEmpty()) {
return;
}
- Collection duplicatedBlocks = from(dtos).transform(DtoToBlock.INSTANCE).toList();
- Collection originBlocks = from(cpdTextBlocks).transform(new CpdTextBlockToBlock(file.getDbKey())).toList();
+ Collection duplicatedBlocks = dtos.stream().map(DtoToBlock.INSTANCE).collect(Collectors.toList());
+ Collection originBlocks = cpdTextBlocks.stream().map(new CpdTextBlockToBlock(file.getDbKey())).collect(Collectors.toList());
LOGGER.trace("Found {} duplicated cpd blocks on file {}", duplicatedBlocks.size(), file.getDbKey());
integrateCrossProjectDuplications.computeCpd(file, originBlocks, duplicatedBlocks);
@@ -155,7 +155,7 @@ public class LoadCrossProjectDuplicationsRepositoryStep implements ComputationSt
private final String fileKey;
private int indexInFile = 0;
- public CpdTextBlockToBlock(String fileKey) {
+ CpdTextBlockToBlock(String fileKey) {
this.fileKey = fileKey;
}
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/duplication/DuplicationRepositoryRule.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/duplication/DuplicationRepositoryRule.java
index 453f987127d..79e8d1d28e6 100644
--- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/duplication/DuplicationRepositoryRule.java
+++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/duplication/DuplicationRepositoryRule.java
@@ -101,7 +101,7 @@ public class DuplicationRepositoryRule extends ExternalResource implements Dupli
component,
new Duplication(
original,
- from(Arrays.asList(duplicates)).transform(TextBlockToInnerDuplicate.INSTANCE)));
+ from(Arrays.asList(duplicates)).transform(TextBlockToInnerDuplicate.INSTANCE).toList()));
return this;
}
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/duplication/DuplicationTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/duplication/DuplicationTest.java
index c68e857d7dc..7fb700bd865 100644
--- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/duplication/DuplicationTest.java
+++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/duplication/DuplicationTest.java
@@ -19,11 +19,9 @@
*/
package org.sonar.ce.task.projectanalysis.duplication;
-import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import org.junit.Rule;
import org.junit.Test;
@@ -51,7 +49,7 @@ public class DuplicationTest {
expectedException.expect(NullPointerException.class);
expectedException.expectMessage("original TextBlock can not be null");
- new Duplication(null, Collections.emptySet());
+ new Duplication(null, Collections.emptyList());
}
@Test
@@ -67,7 +65,7 @@ public class DuplicationTest {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("duplicates can not be empty");
- new Duplication(SOME_ORIGINAL_TEXTBLOCK, Collections.emptySet());
+ new Duplication(SOME_ORIGINAL_TEXTBLOCK, Collections.emptyList());
}
@Test
@@ -75,7 +73,7 @@ public class DuplicationTest {
expectedException.expect(NullPointerException.class);
expectedException.expectMessage("duplicates can not contain null");
- new Duplication(SOME_ORIGINAL_TEXTBLOCK, new HashSet<>(Arrays.asList(mock(Duplicate.class), null, mock(Duplicate.class))));
+ new Duplication(SOME_ORIGINAL_TEXTBLOCK, Arrays.asList(mock(Duplicate.class), null, mock(Duplicate.class)));
}
@Test
@@ -83,7 +81,7 @@ public class DuplicationTest {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("TextBlock of an InnerDuplicate can not be the original TextBlock");
- new Duplication(SOME_ORIGINAL_TEXTBLOCK, new HashSet<>(Arrays.asList(mock(Duplicate.class), new InnerDuplicate(SOME_ORIGINAL_TEXTBLOCK), mock(Duplicate.class))));
+ new Duplication(SOME_ORIGINAL_TEXTBLOCK, Arrays.asList(mock(Duplicate.class), new InnerDuplicate(SOME_ORIGINAL_TEXTBLOCK), mock(Duplicate.class)));
}
@Test
@@ -91,7 +89,7 @@ public class DuplicationTest {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Unsupported type of Duplicate " + MyDuplicate.class.getName());
- new Duplication(SOME_ORIGINAL_TEXTBLOCK, ImmutableSet.of(new MyDuplicate(), new MyDuplicate()));
+ new Duplication(SOME_ORIGINAL_TEXTBLOCK, Arrays.asList(new MyDuplicate(), new MyDuplicate()));
}
private static final class MyDuplicate implements Duplicate {
@@ -104,7 +102,8 @@ public class DuplicationTest {
@Test
public void getOriginal_returns_original() {
- assertThat(new Duplication(SOME_ORIGINAL_TEXTBLOCK, ImmutableSet.of(mock(Duplicate.class))).getOriginal()).isSameAs(SOME_ORIGINAL_TEXTBLOCK);
+ assertThat(new Duplication(SOME_ORIGINAL_TEXTBLOCK, Arrays.asList(new InnerDuplicate(TEXT_BLOCK_1)))
+ .getOriginal()).isSameAs(SOME_ORIGINAL_TEXTBLOCK);
}
@Test
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/duplication/IntegrateCrossProjectDuplicationsTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/duplication/IntegrateCrossProjectDuplicationsTest.java
index 4f1b01ebfa2..a2a66c69f7c 100644
--- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/duplication/IntegrateCrossProjectDuplicationsTest.java
+++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/duplication/IntegrateCrossProjectDuplicationsTest.java
@@ -26,8 +26,10 @@ import java.util.Collections;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.utils.internal.TestSystem2;
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
+import org.sonar.ce.task.log.CeTaskMessages;
import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.ce.task.projectanalysis.component.FileAttributes;
import org.sonar.duplications.block.Block;
@@ -38,29 +40,29 @@ import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import static org.sonar.ce.task.projectanalysis.component.Component.Type.FILE;
import static org.sonar.ce.task.projectanalysis.component.ReportComponent.builder;
public class IntegrateCrossProjectDuplicationsTest {
+ private static final String XOO_LANGUAGE = "xoo";
+ private static final String ORIGIN_FILE_KEY = "ORIGIN_FILE_KEY";
+ private static final Component ORIGIN_FILE = builder(FILE, 1)
+ .setKey(ORIGIN_FILE_KEY)
+ .setFileAttributes(new FileAttributes(false, XOO_LANGUAGE, 1))
+ .build();
+ private static final String OTHER_FILE_KEY = "OTHER_FILE_KEY";
@Rule
public LogTester logTester = new LogTester();
@Rule
public DuplicationRepositoryRule duplicationRepository = DuplicationRepositoryRule.create();
- static final String XOO_LANGUAGE = "xoo";
-
- static final String ORIGIN_FILE_KEY = "ORIGIN_FILE_KEY";
- static final Component ORIGIN_FILE = builder(FILE, 1)
- .setKey(ORIGIN_FILE_KEY)
- .setFileAttributes(new FileAttributes(false, XOO_LANGUAGE, 1))
- .build();
-
- static final String OTHER_FILE_KEY = "OTHER_FILE_KEY";
-
- MapSettings settings = new MapSettings();
-
- IntegrateCrossProjectDuplications underTest = new IntegrateCrossProjectDuplications(settings.asConfig(), duplicationRepository);
+ private TestSystem2 system = new TestSystem2();
+ private MapSettings settings = new MapSettings();
+ private CeTaskMessages ceTaskMessages = mock(CeTaskMessages.class);
+ private IntegrateCrossProjectDuplications underTest = new IntegrateCrossProjectDuplications(settings.asConfig(), duplicationRepository, ceTaskMessages, system);
@Test
public void add_duplications_from_two_blocks() {
@@ -335,10 +337,12 @@ public class IntegrateCrossProjectDuplicationsTest {
@Test
public void log_warning_if_this_deprecated_feature_is_enabled() {
settings.setProperty("sonar.cpd.cross_project", "true");
+ system.setNow(1000L);
- new IntegrateCrossProjectDuplications(settings.asConfig(), duplicationRepository);
+ new IntegrateCrossProjectDuplications(settings.asConfig(), duplicationRepository, ceTaskMessages, system);
assertThat(logTester.logs()).containsExactly("This analysis uses the deprecated cross-project duplication feature.");
+ verify(ceTaskMessages).add(new CeTaskMessages.Message("This project uses the deprecated cross-project duplication feature.", 1000L));
}
private static Duplication crossProjectDuplication(TextBlock original, String otherFileKey, TextBlock duplicate) {
--
2.39.5