aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-scanner-engine/src/test/java
diff options
context:
space:
mode:
authorPierre Guillot <pierre.guillot@sonarsource.com>2024-12-10 15:29:09 +0100
committerSteve Marion <steve.marion@sonarsource.com>2024-12-18 11:13:21 +0100
commitd639a965bce7acafb004906cd07a8f0b5f7af993 (patch)
tree647cd646abddb12dfeeef7e637aa33b4658f1049 /sonar-scanner-engine/src/test/java
parent451c1c2e4856ec3df87f86189fcdb25b31794027 (diff)
downloadsonarqube-d639a965bce7acafb004906cd07a8f0b5f7af993.tar.gz
sonarqube-d639a965bce7acafb004906cd07a8f0b5f7af993.zip
SONAR-22998 fetch active rules with a dedicated endpoint
Co-authored-by: Julien HENRY <julien.henry@sonarsource.com>
Diffstat (limited to 'sonar-scanner-engine/src/test/java')
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesProviderTest.java69
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest.java208
2 files changed, 160 insertions, 117 deletions
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesProviderTest.java
index 4072d462f92..c5f3fceedbc 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesProviderTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesProviderTest.java
@@ -19,13 +19,12 @@
*/
package org.sonar.scanner.rule;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
-import java.util.Date;
-import java.util.LinkedList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.assertj.core.groups.Tuple;
import org.junit.Test;
@@ -36,16 +35,17 @@ import org.sonar.api.batch.rule.internal.DefaultActiveRules;
import org.sonar.api.issue.impact.Severity;
import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.api.rule.RuleKey;
-import org.sonar.api.utils.DateUtils;
-import org.sonarqube.ws.Qualityprofiles.SearchWsResponse.QualityProfile;
+import org.sonar.scanner.bootstrap.ScannerProperties;
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.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import static org.sonar.api.CoreProperties.PROJECT_KEY_PROPERTY;
public class ActiveRulesProviderTest {
+ public static final String PROJECT_KEY = "my-awesome-project";
private final ActiveRulesProvider provider = new ActiveRulesProvider();
private final DefaultActiveRulesLoader loader = mock(DefaultActiveRulesLoader.class);
@@ -57,21 +57,19 @@ public class ActiveRulesProviderTest {
r1.setImpacts(Map.of(SoftwareQuality.MAINTAINABILITY, Severity.HIGH));
- List<LoadedActiveRule> qp1Rules = ImmutableList.of(r1, r2);
- List<LoadedActiveRule> qp2Rules = ImmutableList.of(r2, r3);
- List<LoadedActiveRule> qp3Rules = ImmutableList.of(r1, r3);
+ when(loader.load(PROJECT_KEY)).thenReturn(List.of(r1, r2, r3));
- when(loader.load("qp1")).thenReturn(qp1Rules);
- when(loader.load("qp2")).thenReturn(qp2Rules);
- when(loader.load("qp3")).thenReturn(qp3Rules);
-
- QualityProfiles profiles = mockProfiles("qp1", "qp2", "qp3");
- DefaultActiveRules activeRules = provider.provide(loader, profiles);
+ HashMap<String, String> propertiesMap = new HashMap<>();
+ propertiesMap.put(PROJECT_KEY_PROPERTY, PROJECT_KEY);
+ ScannerProperties scannerProperties = new ScannerProperties(propertiesMap);
+ DefaultActiveRules activeRules = provider.provide(loader, scannerProperties);
assertThat(activeRules.findAll()).hasSize(3);
assertThat(activeRules.findAll()).extracting("ruleKey").containsOnly(
RuleKey.of("rule1", "rule1"), RuleKey.of("rule2", "rule2"), RuleKey.of("rule3", "rule3"));
+ verify(loader).load(PROJECT_KEY);
+
Map<String, ActiveRule> activeRuleByKey = activeRules.findAll().stream().collect(Collectors.toMap(e -> e.ruleKey().rule(), e -> e));
assertThat(((DefaultActiveRule) activeRuleByKey.get("rule1")).impacts())
.containsExactlyInAnyOrderEntriesOf(Map.of(SoftwareQuality.MAINTAINABILITY, Severity.HIGH));
@@ -79,10 +77,6 @@ public class ActiveRulesProviderTest {
assertThat(((DefaultActiveRule) activeRuleByKey.get("rule2")).impacts()).isEmpty();
assertThat(((DefaultActiveRule) activeRuleByKey.get("rule3")).impacts()).isEmpty();
- verify(loader).load("qp1");
- verify(loader).load("qp2");
- verify(loader).load("qp3");
-
assertThat(activeRules.getDeprecatedRuleKeys(RuleKey.of("rule1", "rule1"))).containsOnly("rule1old:rule1old");
verifyNoMoreInteractions(loader);
}
@@ -90,40 +84,33 @@ public class ActiveRulesProviderTest {
@Test
public void testParamsAreTransformed() {
LoadedActiveRule r1 = mockRule("rule1");
- LoadedActiveRule r2 = mockRule("rule2");
- r2.setParams(ImmutableMap.of("foo1", "bar1", "foo2", "bar2"));
+ LoadedActiveRule r2 = mockRule("rule2", b -> b.setParams(Map.of("foo1", "bar1", "foo2", "bar2")));
- List<LoadedActiveRule> qpRules = ImmutableList.of(r1, r2);
- when(loader.load("qp")).thenReturn(qpRules);
+ when(loader.load(PROJECT_KEY)).thenReturn(List.of(r1, r2));
- QualityProfiles profiles = mockProfiles("qp");
- ActiveRules activeRules = provider.provide(loader, profiles);
+ HashMap<String, String> propertiesMap = new HashMap<>();
+ propertiesMap.put(PROJECT_KEY_PROPERTY, PROJECT_KEY);
+ ScannerProperties scannerProperties = new ScannerProperties(propertiesMap);
+ ActiveRules activeRules = provider.provide(loader, scannerProperties);
assertThat(activeRules.findAll()).hasSize(2);
assertThat(activeRules.findAll()).extracting("ruleKey", "params").containsOnly(
Tuple.tuple(RuleKey.of("rule1", "rule1"), ImmutableMap.of()),
Tuple.tuple(RuleKey.of("rule2", "rule2"), ImmutableMap.of("foo1", "bar1", "foo2", "bar2")));
- verify(loader).load("qp");
+ verify(loader).load(PROJECT_KEY);
verifyNoMoreInteractions(loader);
}
- private static QualityProfiles mockProfiles(String... keys) {
- List<QualityProfile> profiles = new LinkedList<>();
-
- for (String k : keys) {
- QualityProfile p = QualityProfile.newBuilder().setKey(k).setLanguage(k).setRulesUpdatedAt(DateUtils.formatDateTime(new Date())).build();
- profiles.add(p);
+ @SafeVarargs
+ private static LoadedActiveRule mockRule(String name, Consumer<LoadedActiveRule>... consumers) {
+ LoadedActiveRule rule = new LoadedActiveRule();
+ rule.setName(name);
+ rule.setRuleKey(RuleKey.of(name, name));
+ rule.setDeprecatedKeys(ImmutableSet.of(RuleKey.of(name + "old", name + "old")));
+ for (Consumer<LoadedActiveRule> consumer : consumers) {
+ consumer.accept(rule);
}
-
- return new QualityProfiles(profiles);
- }
-
- private static LoadedActiveRule mockRule(String name) {
- LoadedActiveRule r = new LoadedActiveRule();
- r.setName(name);
- r.setRuleKey(RuleKey.of(name, name));
- r.setDeprecatedKeys(ImmutableSet.of(RuleKey.of(name + "old", name + "old")));
- return r;
+ return rule;
}
}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest.java
index 59a49084742..cf66faeb655 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest.java
@@ -19,46 +19,49 @@
*/
package org.sonar.scanner.rule;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.util.Collection;
+import com.google.gson.Gson;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
import java.util.stream.IntStream;
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.scanner.rule.LoadedActiveRule;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.Severity;
import org.sonar.scanner.WsTestUtil;
import org.sonar.scanner.http.DefaultScannerWsClient;
import org.sonar.scanner.scan.branch.BranchConfiguration;
-import org.sonarqube.ws.Common;
-import org.sonarqube.ws.Rules;
-import org.sonarqube.ws.Rules.Active;
-import org.sonarqube.ws.Rules.ActiveList;
-import org.sonarqube.ws.Rules.Actives;
-import org.sonarqube.ws.Rules.Rule;
+import static java.util.Map.entry;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import static org.sonar.api.issue.impact.Severity.HIGH;
+import static org.sonar.scanner.rule.DefaultActiveRulesLoader.ActiveRuleGson;
+import static org.sonar.scanner.rule.DefaultActiveRulesLoader.ParamGson;
+import static org.sonar.scanner.rule.DefaultActiveRulesLoader.RuleKeyGson;
-public class DefaultActiveRulesLoaderTest {
+class DefaultActiveRulesLoaderTest {
- private static final int PAGE_SIZE_1 = 150;
- private static final int PAGE_SIZE_2 = 76;
+ private static final int NUMBER_OF_RULES = 150;
private static final RuleKey EXAMPLE_KEY = RuleKey.of("java", "S108");
+ private static final RuleKey CUSTOM_RULE_KEY = RuleKey.of("java", "my-custom-rule");
private static final String FORMAT_KEY = "format";
private static final String FORMAT_VALUE = "^[a-z][a-zA-Z0-9]*$";
+ private static final String PROJECT_KEY = "myProjectKey";
private static final String SEVERITY_VALUE = Severity.MINOR;
private DefaultActiveRulesLoader loader;
private DefaultScannerWsClient wsClient;
- @Before
- public void setUp() {
+ @BeforeEach
+ void setUp() {
wsClient = mock(DefaultScannerWsClient.class);
BranchConfiguration branchConfig = mock(BranchConfiguration.class);
when(branchConfig.isPullRequest()).thenReturn(false);
@@ -66,78 +69,131 @@ public class DefaultActiveRulesLoaderTest {
}
@Test
- public void load_shouldRequestRulesAndParseResponse() {
- int total = PAGE_SIZE_1 + PAGE_SIZE_2;
-
- WsTestUtil.mockStream(wsClient, urlOfPage(1), responseOfSize(1, PAGE_SIZE_1, total));
- WsTestUtil.mockStream(wsClient, urlOfPage(2), responseOfSize(2, PAGE_SIZE_2, total));
-
- Collection<LoadedActiveRule> activeRules = loader.load("c+-test_c+-values-17445");
- assertThat(activeRules).hasSize(total);
- assertThat(activeRules)
- .filteredOn(r -> r.getRuleKey().equals(EXAMPLE_KEY))
- .extracting(LoadedActiveRule::getParams)
- .extracting(p -> p.get(FORMAT_KEY))
- .containsExactly(FORMAT_VALUE);
- assertThat(activeRules)
- .filteredOn(r -> r.getRuleKey().equals(EXAMPLE_KEY))
- .extracting(LoadedActiveRule::getSeverity)
- .containsExactly(SEVERITY_VALUE);
- assertThat(activeRules)
- .filteredOn(r -> r.getRuleKey().equals(EXAMPLE_KEY))
- .extracting(LoadedActiveRule::getImpacts)
- .containsExactlyInAnyOrder(Map.of(SoftwareQuality.MAINTAINABILITY, org.sonar.api.issue.impact.Severity.HIGH));
-
- WsTestUtil.verifyCall(wsClient, urlOfPage(1));
- WsTestUtil.verifyCall(wsClient, urlOfPage(2));
+ void load_shouldRequestRulesAndParseResponse() {
+ WsTestUtil.mockReader(wsClient, getUrl(), response());
+
+ Map<RuleKey, LoadedActiveRule> activeRulesByKey = loader.load(PROJECT_KEY).stream().collect(Collectors.toMap(LoadedActiveRule::getRuleKey, r -> r));
+ assertThat(activeRulesByKey).hasSize(NUMBER_OF_RULES);
+
+ var exampleRule = activeRulesByKey.get(EXAMPLE_KEY);
+ assertThat(exampleRule.getParams()).containsEntry(FORMAT_KEY, FORMAT_VALUE);
+ assertThat(exampleRule.getSeverity()).isEqualTo(SEVERITY_VALUE);
+ assertThat(exampleRule.getImpacts()).containsExactly(entry(SoftwareQuality.MAINTAINABILITY, HIGH));
+
+ var customRule = activeRulesByKey.get(CUSTOM_RULE_KEY);
+ assertThat(customRule.getTemplateRuleKey()).isEqualTo("ruleTemplate");
+
+ WsTestUtil.verifyCall(wsClient, getUrl());
verifyNoMoreInteractions(wsClient);
}
- private String urlOfPage(int page) {
- return "/api/rules/list.protobuf?qprofile=c%2B-test_c%2B-values-17445&ps=500&p=" + page + "";
+ private String getUrl() {
+ return "/api/v2/analysis/active_rules?projectKey=" + PROJECT_KEY;
}
- /**
- * Generates an imaginary protobuf result.
- *
- * @param pageIndex page index, that the response should contain
- * @param numberOfRules the number of rules, that the response should contain
- * @param total the number of results on all pages
- * @return the binary stream
- */
- private InputStream responseOfSize(int pageIndex, int numberOfRules, int total) {
- Rules.ListResponse.Builder rules = Rules.ListResponse.newBuilder();
- Actives.Builder actives = Actives.newBuilder();
-
- IntStream.rangeClosed(1, numberOfRules)
+ private Reader response() {
+ List<ActiveRuleGson> activeRules = new ArrayList<>();
+
+ IntStream.rangeClosed(1, NUMBER_OF_RULES - 1)
.mapToObj(i -> RuleKey.of("java", "S" + i))
.forEach(key -> {
+ ActiveRuleGsonBuilder builder = new ActiveRuleGsonBuilder();
- Rule.Builder ruleBuilder = Rule.newBuilder();
- ruleBuilder.setKey(key.toString());
- rules.addRules(ruleBuilder);
+ builder.setRuleKey(new RuleKeyGson(key.repository(), key.rule()));
- Active.Builder activeBuilder = Active.newBuilder();
- activeBuilder.setCreatedAt("2014-05-27T15:50:45+0100");
- activeBuilder.setUpdatedAt("2014-05-27T15:50:45+0100");
+ builder.setCreatedAt("2014-05-27T15:50:45+0100");
+ builder.setUpdatedAt("2014-05-27T15:50:45+0100");
if (EXAMPLE_KEY.equals(key)) {
- activeBuilder.addParams(Rules.Active.Param.newBuilder().setKey(FORMAT_KEY).setValue(FORMAT_VALUE));
- activeBuilder.setSeverity(SEVERITY_VALUE);
- activeBuilder.setImpacts(Rules.Impacts.newBuilder().addImpacts(Common.Impact.newBuilder()
- .setSoftwareQuality(Common.SoftwareQuality.MAINTAINABILITY)
- .setSeverity(Common.ImpactSeverity.HIGH).build()).build());
+ builder.setParams(List.of(new ParamGson(FORMAT_KEY, FORMAT_VALUE)));
+ builder.setSeverity(SEVERITY_VALUE);
+ builder.setImpacts(Map.of(SoftwareQuality.MAINTAINABILITY, HIGH));
}
- ActiveList activeList = Rules.ActiveList.newBuilder().addActiveList(activeBuilder).build();
- actives.putAllActives(Map.of(key.toString(), activeList));
+
+ activeRules.add(builder.build());
});
- rules.setActives(actives);
- rules.setPaging(Common.Paging.newBuilder()
- .setTotal(total)
- .setPageIndex(pageIndex)
- .setPageSize(numberOfRules)
- .build());
- return new ByteArrayInputStream(rules.build().toByteArray());
+ ActiveRuleGsonBuilder builder = new ActiveRuleGsonBuilder();
+ builder.setRuleKey(new RuleKeyGson(CUSTOM_RULE_KEY.repository(), CUSTOM_RULE_KEY.rule()));
+ builder.setCreatedAt("2014-05-27T15:50:45+0100");
+ builder.setUpdatedAt("2014-05-27T15:50:45+0100");
+ builder.setTemplateRuleKey("java:ruleTemplate");
+ activeRules.add(builder.build());
+
+ return toReader(activeRules);
+ }
+
+ private static Reader toReader(List<ActiveRuleGson> activeRules) {
+ String json = new Gson().toJson(activeRules);
+ return new StringReader(json);
+ }
+
+ private static class ActiveRuleGsonBuilder {
+ private RuleKeyGson ruleKey;
+ private String name;
+ private String severity;
+ private String createdAt;
+ private String updatedAt;
+ private String internalKey;
+ private String language;
+ private String templateRuleKey;
+ private String qProfilKey;
+ private final List<RuleKeyGson> deprecatedKeys = new ArrayList<>();
+ private final List<ParamGson> params = new ArrayList<>();
+ private final Map<SoftwareQuality, org.sonar.api.issue.impact.Severity> impacts = new EnumMap<>(SoftwareQuality.class);
+
+ public void setRuleKey(RuleKeyGson ruleKey) {
+ this.ruleKey = ruleKey;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setSeverity(String severity) {
+ this.severity = severity;
+ }
+
+ public void setCreatedAt(String createdAt) {
+ this.createdAt = createdAt;
+ }
+
+ public void setUpdatedAt(String updatedAt) {
+ this.updatedAt = updatedAt;
+ }
+
+ public void setInternalKey(String internalKey) {
+ this.internalKey = internalKey;
+ }
+
+ public void setLanguage(String language) {
+ this.language = language;
+ }
+
+ public void setTemplateRuleKey(String templateRuleKey) {
+ this.templateRuleKey = templateRuleKey;
+ }
+
+ public void setQProfilKey(String qProfilKey) {
+ this.qProfilKey = qProfilKey;
+ }
+
+ public void setParams(List<ParamGson> params) {
+ this.params.clear();
+ this.params.addAll(params);
+ }
+
+ public void addAllDeprecatedKeys(List<RuleKeyGson> deprecatedKeys) {
+ this.deprecatedKeys.addAll(deprecatedKeys);
+ }
+
+ public void setImpacts(Map<SoftwareQuality, org.sonar.api.issue.impact.Severity> impacts) {
+ this.impacts.clear();
+ this.impacts.putAll(impacts);
+ }
+
+ public ActiveRuleGson build() {
+ return new ActiveRuleGson(ruleKey, name, severity, createdAt, updatedAt, internalKey, language, templateRuleKey, qProfilKey, deprecatedKeys, params, impacts);
+ }
}
}