aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDto.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/DebtCalculator.java11
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/commonrule/CommonRule.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/ExternalRuleCreator.java1
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/DebtCalculatorTest.java11
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/TransitionActionTest.java2
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java4
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java2
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/externalissue/ExternalIssueImporter.java5
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ReportParserTest.java23
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/issues/ExternalIssuesMediumTest.java12
-rw-r--r--sonar-scanner-engine/src/test/resources/mediumtest/xoo/sample/externalIssues.json16
-rw-r--r--sonar-scanner-engine/src/test/resources/org/sonar/scanner/externalissue/report.json25
-rw-r--r--sonar-scanner-engine/src/test/resources/org/sonar/scanner/externalissue/report_missing_message.json28
-rw-r--r--tests/projects/shared/xoo-sample/externalIssues.json45
-rw-r--r--tests/src/test/java/org/sonarqube/tests/issue/ExternalIssueTest.java99
17 files changed, 251 insertions, 41 deletions
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDto.java
index 0213e3106e5..3f72a51740a 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDto.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDto.java
@@ -733,7 +733,7 @@ public final class IssueDto implements Serializable {
issue.setUpdateDate(longToDate(issueUpdateDate));
issue.setSelectedAt(selectedAt);
issue.setLocations(parseLocations());
- issue.setFromExternalRuleEngine(isExternal);
+ issue.setIsFromExternalRuleEngine(isExternal);
return issue;
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/DebtCalculator.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/DebtCalculator.java
index 328447ed02a..c896d0de584 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/DebtCalculator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/DebtCalculator.java
@@ -40,19 +40,22 @@ public class DebtCalculator {
@CheckForNull
public Duration calculate(DefaultIssue issue) {
+ if (issue.isFromExternalRuleEngine()) {
+ return issue.effort();
+ }
Rule rule = ruleRepository.getByKey(issue.ruleKey());
DebtRemediationFunction fn = rule.getRemediationFunction();
if (fn != null) {
verifyEffortToFix(issue, fn);
Duration debt = Duration.create(0);
- String gapMultiplier =fn.gapMultiplier();
+ String gapMultiplier = fn.gapMultiplier();
if (fn.type().usesGapMultiplier() && !Strings.isNullOrEmpty(gapMultiplier)) {
- int effortToFixValue = MoreObjects.firstNonNull(issue.effortToFix(), 1).intValue();
+ int effortToFixValue = MoreObjects.firstNonNull(issue.gap(), 1).intValue();
// TODO convert to Duration directly in Rule#remediationFunction -> better performance + error handling
debt = durations.decode(gapMultiplier).multiply(effortToFixValue);
}
- String baseEffort= fn.baseEffort();
+ String baseEffort = fn.baseEffort();
if (fn.type().usesBaseEffort() && !Strings.isNullOrEmpty(baseEffort)) {
// TODO convert to Duration directly in Rule#remediationFunction -> better performance + error handling
debt = debt.add(durations.decode(baseEffort));
@@ -63,7 +66,7 @@ public class DebtCalculator {
}
private static void verifyEffortToFix(DefaultIssue issue, DebtRemediationFunction fn) {
- if (Type.CONSTANT_ISSUE.equals(fn.type()) && issue.effortToFix() != null) {
+ if (Type.CONSTANT_ISSUE.equals(fn.type()) && issue.gap() != null) {
throw new IllegalArgumentException("Rule '" + issue.getRuleKey() + "' can not use 'Constant/issue' remediation function " +
"because this rule does not have a fixed remediation cost.");
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java
index 8b134cf9d18..5344410c459 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java
@@ -167,7 +167,7 @@ public class TrackerRawInputFactory {
dbLocationsBuilder.addFlow(dbFlowBuilder);
}
}
- issue.setFromExternalRuleEngine(false);
+ issue.setIsFromExternalRuleEngine(false);
issue.setLocations(dbLocationsBuilder.build());
return issue;
}
@@ -204,7 +204,7 @@ public class TrackerRawInputFactory {
dbLocationsBuilder.addFlow(dbFlowBuilder);
}
}
- issue.setFromExternalRuleEngine(true);
+ issue.setIsFromExternalRuleEngine(true);
issue.setLocations(dbLocationsBuilder.build());
issue.setType(toRuleType(reportIssue.getType()));
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/commonrule/CommonRule.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/commonrule/CommonRule.java
index 9f1a84bafaa..397f9305355 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/commonrule/CommonRule.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/commonrule/CommonRule.java
@@ -55,7 +55,7 @@ public abstract class CommonRule {
issue.setSeverity(activeRule.get().getSeverity());
issue.setLine(null);
issue.setChecksum("");
- issue.setFromExternalRuleEngine(false);
+ issue.setIsFromExternalRuleEngine(false);
}
}
return issue;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ExternalRuleCreator.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ExternalRuleCreator.java
index 1f96b689c94..30ee1919563 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/ExternalRuleCreator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ExternalRuleCreator.java
@@ -61,7 +61,6 @@ public class ExternalRuleCreator {
.setUpdatedAt(system2.now()));
Rule newRule = new RuleImpl(dao.selectOrFailByKey(dbSession, external.getKey()));
- // TODO write rule repository if needed
ruleIndexer.commitAndIndex(dbSession, newRule.getId());
return newRule;
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/DebtCalculatorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/DebtCalculatorTest.java
index f7154ba9de7..67a9d2ebd11 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/DebtCalculatorTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/DebtCalculatorTest.java
@@ -22,6 +22,7 @@ package org.sonar.server.computation.task.projectanalysis.issue;
import org.junit.Test;
import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction;
+import org.sonar.api.utils.Duration;
import org.sonar.api.utils.Durations;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.db.rule.RuleTesting;
@@ -73,6 +74,16 @@ public class DebtCalculatorTest {
}
@Test
+ public void copy_effort_for_external_issues() {
+ issue.setGap(null);
+ issue.setIsFromExternalRuleEngine(true);
+ issue.setEffort(Duration.create(20l));
+ rule.setFunction(null);
+
+ assertThat(underTest.calculate(issue).toMinutes()).isEqualTo(20l);
+ }
+
+ @Test
public void constant_function() {
int constant = 2;
issue.setGap(null);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/TransitionActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/TransitionActionTest.java
index 6ada52d8ace..cc5c1b113a0 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/TransitionActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/TransitionActionTest.java
@@ -117,7 +117,7 @@ public class TransitionActionTest {
loginAndAddProjectPermission("john", ISSUE_ADMIN);
context.issue()
- .setFromExternalRuleEngine(true)
+ .setIsFromExternalRuleEngine(true)
.setStatus(STATUS_CLOSED);
action.execute(ImmutableMap.of("transition", "close"), context);
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java
index 0add84d5a82..f1339f27a69 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java
@@ -245,8 +245,8 @@ public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure.
return isFromExternalRuleEngine;
}
- public DefaultIssue setFromExternalRuleEngine(boolean fromExternalRuleEngine) {
- isFromExternalRuleEngine = fromExternalRuleEngine;
+ public DefaultIssue setIsFromExternalRuleEngine(boolean isFromExternalRuleEngine) {
+ this.isFromExternalRuleEngine = isFromExternalRuleEngine;
return this;
}
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java
index e302c0bd3e3..7f5c4fdf806 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java
@@ -170,7 +170,7 @@ public class DefaultIssueBuilder implements Issuable.IssueBuilder {
issue.setCopied(false);
issue.setBeingClosed(false);
issue.setOnDisabledRule(false);
- issue.setFromExternalRuleEngine(isFromExternalRuleEngine);
+ issue.setIsFromExternalRuleEngine(isFromExternalRuleEngine);
return issue;
}
}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/externalissue/ExternalIssueImporter.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/externalissue/ExternalIssueImporter.java
index 4a5e35e96f4..99100318b68 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/externalissue/ExternalIssueImporter.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/externalissue/ExternalIssueImporter.java
@@ -107,9 +107,12 @@ public class ExternalIssueImporter {
InputFile file = findFile(context, location.filePath);
if (file != null) {
newLocation
- .message(location.message)
.on(file);
+ if (location.message != null) {
+ newLocation.message(location.message);
+ }
+
if (location.textRange != null) {
if (location.textRange.startColumn != null) {
TextPointer start = file.newPointer(location.textRange.startLine, location.textRange.startColumn);
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ReportParserTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ReportParserTest.java
index e13e64d6b85..add4404b2a9 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ReportParserTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ReportParserTest.java
@@ -39,7 +39,7 @@ public class ReportParserTest {
System.out.println(Paths.get("org/sonar/scanner/externalissue/report.json").toAbsolutePath());
Report report = parser.parse();
- assertThat(report.issues).hasSize(3);
+ assertThat(report.issues).hasSize(4);
assertThat(report.issues[0].engineId).isEqualTo("eslint");
assertThat(report.issues[0].ruleId).isEqualTo("rule1");
assertThat(report.issues[0].severity).isEqualTo("MAJOR");
@@ -52,6 +52,19 @@ public class ReportParserTest {
assertThat(report.issues[0].primaryLocation.textRange.endColumn).isEqualTo(4);
assertThat(report.issues[0].primaryLocation.textRange.endLine).isEqualTo(3);
assertThat(report.issues[0].secondaryLocations).isNull();
+
+ assertThat(report.issues[3].engineId).isEqualTo("eslint");
+ assertThat(report.issues[3].ruleId).isEqualTo("rule3");
+ assertThat(report.issues[3].severity).isEqualTo("MAJOR");
+ assertThat(report.issues[3].effortMinutes).isNull();
+ assertThat(report.issues[3].type).isEqualTo("BUG");
+ assertThat(report.issues[3].secondaryLocations).hasSize(2);
+ assertThat(report.issues[3].secondaryLocations[0].filePath).isEqualTo("file1.js");
+ assertThat(report.issues[3].secondaryLocations[0].message).isEqualTo("fix the bug here");
+ assertThat(report.issues[3].secondaryLocations[0].textRange.startLine).isEqualTo(1);
+ assertThat(report.issues[3].secondaryLocations[1].filePath).isEqualTo("file2.js");
+ assertThat(report.issues[3].secondaryLocations[1].message).isNull();
+ assertThat(report.issues[3].secondaryLocations[1].textRange.startLine).isEqualTo(2);
}
private Path path(String reportName) {
@@ -121,4 +134,12 @@ public class ReportParserTest {
exception.expectMessage("missing mandatory field 'filePath'");
parser.parse();
}
+
+ @Test
+ public void fail_if_message_not_set_in_primaryLocation() {
+ ReportParser parser = new ReportParser(path("report_missing_message.json"));
+ exception.expect(IllegalStateException.class);
+ exception.expectMessage("missing mandatory field 'message'");
+ parser.parse();
+ }
}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/issues/ExternalIssuesMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/issues/ExternalIssuesMediumTest.java
index 6d406300c3b..92e01b6491d 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/issues/ExternalIssuesMediumTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/issues/ExternalIssuesMediumTest.java
@@ -28,7 +28,6 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.utils.log.LoggersTest;
import org.sonar.scanner.mediumtest.ScannerMediumTester;
import org.sonar.scanner.mediumtest.TaskResult;
import org.sonar.scanner.protocol.Constants.Severity;
@@ -111,18 +110,23 @@ public class ExternalIssuesMediumTest {
assertThat(issue.getTextRange().getStartOffset()).isEqualTo(0);
assertThat(issue.getTextRange().getEndOffset()).isEqualTo(24);
- // One file-level issue in helloscala
+ // One file-level issue in helloscala, with secondary location
List<ExternalIssue> externalIssues2 = result.externalIssuesFor(result.inputFile("xources/hello/helloscala.xoo"));
assertThat(externalIssues2).hasSize(1);
issue = externalIssues2.iterator().next();
- assertThat(issue.getFlowCount()).isZero();
+ assertThat(issue.getFlowCount()).isEqualTo(2);
assertThat(issue.getMsg()).isEqualTo("fix the bug here");
assertThat(issue.getRuleKey()).isEqualTo("rule3");
assertThat(issue.getSeverity()).isEqualTo(Severity.MAJOR);
assertThat(issue.getType()).isEqualTo(IssueType.BUG);
assertThat(issue.hasTextRange()).isFalse();
-
+ assertThat(issue.getFlow(0).getLocationCount()).isOne();
+ assertThat(issue.getFlow(0).getLocation(0).getTextRange().getStartLine()).isOne();
+ assertThat(issue.getFlow(1).getLocationCount()).isOne();
+ assertThat(issue.getFlow(1).getLocation(0).getTextRange().getStartLine()).isEqualTo(3);
+
+
// one issue is located in a non-existing file
assertThat(logs.logs()).contains("External issues ignored for 1 unknown files, including: invalidFile");
diff --git a/sonar-scanner-engine/src/test/resources/mediumtest/xoo/sample/externalIssues.json b/sonar-scanner-engine/src/test/resources/mediumtest/xoo/sample/externalIssues.json
index 0e50bedd8dc..539533af78f 100644
--- a/sonar-scanner-engine/src/test/resources/mediumtest/xoo/sample/externalIssues.json
+++ b/sonar-scanner-engine/src/test/resources/mediumtest/xoo/sample/externalIssues.json
@@ -50,7 +50,21 @@
"primaryLocation": {
"message": "fix the bug here",
"filePath": "xources/hello/helloscala.xoo"
- }
+ },
+ "secondaryLocations": [
+ {
+ "filePath": "xources/hello/HelloJava.xoo",
+ "textRange": {
+ "startLine": 1
+ }
+ },
+ {
+ "filePath": "xources/hello/HelloJava.xoo",
+ "textRange": {
+ "startLine": 3
+ }
+ }
+ ]
}
]
} \ No newline at end of file
diff --git a/sonar-scanner-engine/src/test/resources/org/sonar/scanner/externalissue/report.json b/sonar-scanner-engine/src/test/resources/org/sonar/scanner/externalissue/report.json
index 06627d7106b..b951311436b 100644
--- a/sonar-scanner-engine/src/test/resources/org/sonar/scanner/externalissue/report.json
+++ b/sonar-scanner-engine/src/test/resources/org/sonar/scanner/externalissue/report.json
@@ -39,6 +39,31 @@
"message": "fix the bug here",
"filePath": "file3.js"
}
+ },
+ {
+ "engineId": "eslint",
+ "ruleId": "rule3",
+ "severity": "MAJOR",
+ "type": "BUG",
+ "primaryLocation": {
+ "message": "fix the bug here",
+ "filePath": "file3.js"
+ },
+ "secondaryLocations": [
+ {
+ "message": "fix the bug here",
+ "filePath": "file1.js",
+ "textRange": {
+ "startLine": 1
+ }
+ },
+ {
+ "filePath": "file2.js",
+ "textRange": {
+ "startLine": 2
+ }
+ }
+ ]
}
]
}
diff --git a/sonar-scanner-engine/src/test/resources/org/sonar/scanner/externalissue/report_missing_message.json b/sonar-scanner-engine/src/test/resources/org/sonar/scanner/externalissue/report_missing_message.json
new file mode 100644
index 00000000000..c191559faf7
--- /dev/null
+++ b/sonar-scanner-engine/src/test/resources/org/sonar/scanner/externalissue/report_missing_message.json
@@ -0,0 +1,28 @@
+{
+"issues" : [
+ {
+ "engineId": "eslint",
+ "ruleId": "rule1",
+ "severity": "MAJOR",
+ "type": "CODE_SMELL",
+ "primaryLocation": {
+ "message": "fix the issue here",
+ "filePath": "file1.js",
+ "textRange": {
+ "startLine": 1,
+ "endLine": 2
+ }
+ }
+ },
+ {
+ "engineId": "eslint",
+ "ruleId": "rule2",
+ "severity": "MAJOR",
+ "type": "BUG",
+ "primaryLocation": {
+ "filePath": "file1.js"
+ }
+ }
+]
+}
+
diff --git a/tests/projects/shared/xoo-sample/externalIssues.json b/tests/projects/shared/xoo-sample/externalIssues.json
new file mode 100644
index 00000000000..9be94f4cae2
--- /dev/null
+++ b/tests/projects/shared/xoo-sample/externalIssues.json
@@ -0,0 +1,45 @@
+{
+"issues" : [
+ {
+ "engineId": "externalXoo",
+ "ruleId": "rule1",
+ "severity": "MAJOR",
+ "type": "CODE_SMELL",
+ "effortMinutes": 50,
+ "primaryLocation": {
+ "message": "fix the issue here",
+ "filePath": "src/main/xoo/sample/Sample.xoo",
+ "textRange": {
+ "startLine": 5,
+ "startColumn": 2,
+ "endLine": 5,
+ "endColumn": 21
+ }
+ }
+ },
+ {
+ "engineId": "externalXoo",
+ "ruleId": "rule2",
+ "severity": "CRITICAL",
+ "type": "BUG",
+ "primaryLocation": {
+ "message": "fix the bug here",
+ "filePath": "src/main/xoo/sample/Sample.xoo"
+ },
+ "secondaryLocations": [
+ {
+ "filePath": "src/main/xoo/sample/Sample.xoo",
+ "textRange": {
+ "startLine": 1
+ }
+ },
+ {
+ "filePath": "unknown",
+ "textRange": {
+ "startLine": 3
+ }
+ }
+ ]
+ }
+]
+} \ No newline at end of file
diff --git a/tests/src/test/java/org/sonarqube/tests/issue/ExternalIssueTest.java b/tests/src/test/java/org/sonarqube/tests/issue/ExternalIssueTest.java
index d8d4677560c..4a1f4b91a7b 100644
--- a/tests/src/test/java/org/sonarqube/tests/issue/ExternalIssueTest.java
+++ b/tests/src/test/java/org/sonarqube/tests/issue/ExternalIssueTest.java
@@ -19,10 +19,11 @@
*/
package org.sonarqube.tests.issue;
-import com.sonar.orchestrator.build.SonarScanner;
+import com.sonar.orchestrator.Orchestrator;
+import java.util.Collections;
import java.util.List;
-import java.util.stream.Collectors;
import org.junit.Before;
+import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.sonarqube.qa.util.Tester;
@@ -35,9 +36,15 @@ import util.ItUtils;
import static org.assertj.core.api.Assertions.assertThat;
-public class ExternalIssueTest extends AbstractIssueTest {
+public class ExternalIssueTest {
private static final String PROJECT_KEY = "project";
+ // This class uses its own instance of the server because it creates external rules in it
+ @ClassRule
+ public static final Orchestrator ORCHESTRATOR = ItUtils.newOrchestratorBuilder()
+ .addPlugin(ItUtils.xooPlugin())
+ .build();
+
@Rule
public Tester tester = new Tester(ORCHESTRATOR);
@@ -50,45 +57,95 @@ public class ExternalIssueTest extends AbstractIssueTest {
@Test
public void should_import_external_issues_and_create_external_rules() {
- noExternalRuleAndNoIssues();
+ noIssues();
+ ruleDoesntExist("external_xoo:OneExternalIssuePerLine");
- SonarScanner sonarScanner = ItUtils.runProjectAnalysis(ORCHESTRATOR, "shared/xoo-sample",
+ ItUtils.runProjectAnalysis(ORCHESTRATOR, "shared/xoo-sample",
"sonar.oneExternalIssuePerLine.activate", "true");
List<Issue> issuesList = tester.wsClient().issues().search(new SearchRequest()).getIssuesList();
assertThat(issuesList).hasSize(17);
assertThat(issuesList).allMatch(issue -> "external_xoo:OneExternalIssuePerLine".equals(issue.getRule()));
assertThat(issuesList).allMatch(issue -> "This issue is generated on each line".equals(issue.getMessage()));
- assertThat(issuesList).allMatch(issue -> "This issue is generated on each line".equals(issue.getMessage()));
assertThat(issuesList).allMatch(issue -> Severity.MAJOR.equals(issue.getSeverity()));
- assertThat(issuesList).allMatch(issue -> RuleType.CODE_SMELL.equals(issue.getType()));
+ assertThat(issuesList).allMatch(issue -> RuleType.BUG.equals(issue.getType()));
assertThat(issuesList).allMatch(issue -> "sample:src/main/xoo/sample/Sample.xoo".equals(issue.getComponent()));
assertThat(issuesList).allMatch(issue -> "OPEN".equals(issue.getStatus()));
assertThat(issuesList).allMatch(issue -> issue.getExternalRuleEngine().equals("xoo"));
- List<org.sonarqube.ws.Rules.Rule> rulesList = tester.wsClient().rules()
- .search(new org.sonarqube.ws.client.rules.SearchRequest().setIsExternal(Boolean.toString(true))).getRulesList();
- List<org.sonarqube.ws.Rules.Rule> externalRules = rulesList.stream().filter(rule -> rule.getIsExternal()).collect(Collectors.toList());
-
- assertThat(externalRules).hasSize(1);
- assertThat(externalRules.get(0).getKey()).isEqualTo("external_xoo:OneExternalIssuePerLine");
- assertThat(externalRules.get(0).getIsTemplate()).isFalse();
- assertThat(externalRules.get(0).getIsExternal()).isTrue();
- assertThat(externalRules.get(0).getTags().getTagsCount()).isEqualTo(0);
- assertThat(externalRules.get(0).getScope()).isEqualTo(RuleScope.ALL);
+ ruleExists("external_xoo:OneExternalIssuePerLine");
// second analysis, issue tracking should work
- sonarScanner = ItUtils.runProjectAnalysis(ORCHESTRATOR, "shared/xoo-sample",
+ ItUtils.runProjectAnalysis(ORCHESTRATOR, "shared/xoo-sample",
"sonar.oneExternalIssuePerLine.activate", "true");
issuesList = tester.wsClient().issues().search(new SearchRequest()).getIssuesList();
assertThat(issuesList).hasSize(17);
}
- private void noExternalRuleAndNoIssues() {
+ @Test
+ public void should_import_external_issues_from_json_report_and_create_external_rules() {
+ noIssues();
+ ruleDoesntExist("external_externalXoo:rule1");
+ ruleDoesntExist("external_externalXoo:rule2");
+
+ ItUtils.runProjectAnalysis(ORCHESTRATOR, "shared/xoo-sample",
+ "sonar.externalIssuesReportPaths", "externalIssues.json");
+
+ List<Issue> issuesList = tester.wsClient().issues().search(new SearchRequest()
+ .setRules(Collections.singletonList("external_externalXoo:rule1"))).getIssuesList();
+ assertThat(issuesList).hasSize(1);
+
+ assertThat(issuesList.get(0).getRule()).isEqualTo("external_externalXoo:rule1");
+ assertThat(issuesList.get(0).getMessage()).isEqualTo("fix the issue here");
+ assertThat(issuesList.get(0).getSeverity()).isEqualTo(Severity.MAJOR);
+ assertThat(issuesList.get(0).getType()).isEqualTo(RuleType.CODE_SMELL);
+ assertThat(issuesList.get(0).getComponent()).isEqualTo("sample:src/main/xoo/sample/Sample.xoo");
+ assertThat(issuesList.get(0).getStatus()).isEqualTo("OPEN");
+ assertThat(issuesList.get(0).getEffort()).isEqualTo("20min");
+ assertThat(issuesList.get(0).getExternalRuleEngine()).isEqualTo("externalXoo");
+
+ issuesList = tester.wsClient().issues().search(new SearchRequest()
+ .setRules(Collections.singletonList("external_externalXoo:rule2"))).getIssuesList();
+ assertThat(issuesList).hasSize(1);
+
+ assertThat(issuesList.get(0).getRule()).isEqualTo("external_externalXoo:rule2");
+ assertThat(issuesList.get(0).getMessage()).isEqualTo("fix the bug here");
+ assertThat(issuesList.get(0).getSeverity()).isEqualTo(Severity.CRITICAL);
+ assertThat(issuesList.get(0).getType()).isEqualTo(RuleType.BUG);
+ assertThat(issuesList.get(0).getComponent()).isEqualTo("sample:src/main/xoo/sample/Sample.xoo");
+ assertThat(issuesList.get(0).getStatus()).isEqualTo("OPEN");
+ assertThat(issuesList.get(0).getExternalRuleEngine()).isEqualTo("externalXoo");
+
+ ruleExists("external_externalXoo:rule1");
+ ruleExists("external_externalXoo:rule2");
+ }
+
+ private void ruleDoesntExist(String key) {
List<org.sonarqube.ws.Rules.Rule> rulesList = tester.wsClient().rules()
- .search(new org.sonarqube.ws.client.rules.SearchRequest().setIsExternal(Boolean.toString(true))).getRulesList();
- assertThat(rulesList).noneMatch(rule -> rule.getIsExternal());
+ .search(new org.sonarqube.ws.client.rules.SearchRequest()
+ .setRuleKey(key)
+ .setIsExternal(Boolean.toString(true)))
+ .getRulesList();
+ assertThat(rulesList).isEmpty();
+
+ }
+
+ private void ruleExists(String key) {
+ List<org.sonarqube.ws.Rules.Rule> rulesList = tester.wsClient().rules()
+ .search(new org.sonarqube.ws.client.rules.SearchRequest()
+ .setRuleKey(key)
+ .setIsExternal(Boolean.toString(true)))
+ .getRulesList();
+
+ assertThat(rulesList).hasSize(1);
+ assertThat(rulesList.get(0).getKey()).isEqualTo(key);
+ assertThat(rulesList.get(0).getIsTemplate()).isFalse();
+ assertThat(rulesList.get(0).getIsExternal()).isTrue();
+ assertThat(rulesList.get(0).getTags().getTagsCount()).isEqualTo(0);
+ assertThat(rulesList.get(0).getScope()).isEqualTo(RuleScope.ALL);
+ }
+ private void noIssues() {
List<Issue> issuesList = tester.wsClient().issues().search(new SearchRequest()).getIssuesList();
assertThat(issuesList).isEmpty();
}