Skip to content

Commit d83642f

Browse files
DBD-200 Add Dataflow Bug Detection rules to the default quality profiley (#1144)
1 parent 8626d32 commit d83642f

File tree

3 files changed

+97
-27
lines changed

3 files changed

+97
-27
lines changed

sonar-python-plugin/src/main/java/org/sonar/plugins/python/PythonProfile.java

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,40 +41,42 @@ public class PythonProfile implements BuiltInQualityProfilesDefinition {
4141
static final String PROFILE_LOCATION = RESOURCE_FOLDER + "/Sonar_way_profile.json";
4242
static final String SECURITY_RULES_CLASS_NAME = "com.sonar.plugins.security.api.PythonRules";
4343
static final String SECURITY_RULE_KEYS_METHOD_NAME = "getRuleKeys";
44-
static final String SECURITY_RULE_REPO_METHOD_NAME = "getRepositoryKey";
44+
static final String DBD_RULES_CLASS_NAME = "com.sonarsource.plugins.dbd.api.PythonRules";
45+
static final String DBD_RULE_KEYS_METHOD_NAME = "getDataflowBugDetectionRuleKeys";
46+
static final String GET_REPOSITORY_KEY = "getRepositoryKey";
47+
4548

4649
@Override
4750
public void define(Context context) {
4851
NewBuiltInQualityProfile profile = context.createBuiltInQualityProfile(PROFILE_NAME, Python.KEY);
4952
BuiltInQualityProfileJsonLoader.load(profile, CheckList.REPOSITORY_KEY, PROFILE_LOCATION);
50-
getSecurityRuleKeys(SECURITY_RULES_CLASS_NAME, SECURITY_RULE_KEYS_METHOD_NAME, SECURITY_RULE_REPO_METHOD_NAME)
53+
getSecurityRuleKeys()
54+
.forEach(key -> profile.activateRule(key.repository(), key.rule()));
55+
getDataflowBugDetectionRuleKeys()
5156
.forEach(key -> profile.activateRule(key.repository(), key.rule()));
5257
profile.done();
5358
}
5459

55-
// Visible for testing
56-
static Set<RuleKey> getSecurityRuleKeys(String className, String ruleKeysMethodName, String ruleRepoMethodName) {
57-
try {
60+
static Set<RuleKey> getSecurityRuleKeys() {
61+
return getExternalRuleKeys(SECURITY_RULES_CLASS_NAME, SECURITY_RULE_KEYS_METHOD_NAME, "security");
62+
}
63+
64+
static Set<RuleKey> getDataflowBugDetectionRuleKeys() {
65+
return getExternalRuleKeys(DBD_RULES_CLASS_NAME, DBD_RULE_KEYS_METHOD_NAME, "dataflow bug detection");
66+
}
5867

68+
@SuppressWarnings("unchecked")
69+
static Set<RuleKey> getExternalRuleKeys(String className, String ruleKeysMethodName, String rulesCategory) {
70+
try {
5971
Class<?> rulesClass = Class.forName(className);
6072
Method getRuleKeysMethod = rulesClass.getMethod(ruleKeysMethodName);
6173
Set<String> ruleKeys = (Set<String>) getRuleKeysMethod.invoke(null);
62-
Method getRepositoryKeyMethod = rulesClass.getMethod(ruleRepoMethodName);
74+
Method getRepositoryKeyMethod = rulesClass.getMethod(GET_REPOSITORY_KEY);
6375
String repositoryKey = (String) getRepositoryKeyMethod.invoke(null);
6476
return ruleKeys.stream().map(k -> RuleKey.of(repositoryKey, k)).collect(Collectors.toSet());
65-
66-
} catch (ClassNotFoundException e) {
67-
LOG.debug(className + " is not found, " + securityRuleMessage(e));
68-
} catch (NoSuchMethodException e) {
69-
LOG.debug("Method not found on " + className +", " + securityRuleMessage(e));
70-
} catch (IllegalAccessException | InvocationTargetException e) {
71-
LOG.debug(e.getClass().getSimpleName() + ": " + securityRuleMessage(e));
77+
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
78+
LOG.debug(String.format("[%s], no %s rules added to Sonar way Python profile: %s", e.getClass().getSimpleName(), rulesCategory, e.getMessage()));
7279
}
73-
7480
return Collections.emptySet();
7581
}
76-
77-
private static String securityRuleMessage(Exception e) {
78-
return "no security rules added to Sonar way Python profile: " + e.getMessage();
79-
}
8082
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* SonarQube Python Plugin
3+
* Copyright (C) 2011-2022 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package com.sonarsource.plugins.dbd.api;
21+
22+
import java.util.HashSet;
23+
import java.util.Set;
24+
25+
/**
26+
* Class required to test SonarWay for DBD rules
27+
*/
28+
public class PythonRules {
29+
public static Set<String> ruleKeys = new HashSet<>();
30+
31+
public static boolean throwOnCall = false;
32+
33+
public static Set<String> getDataflowBugDetectionRuleKeys() {
34+
if (throwOnCall) {
35+
throw new RuntimeException("Boom!");
36+
}
37+
return ruleKeys;
38+
}
39+
40+
public static String getRepositoryKey() {
41+
return "dbd-repo-key";
42+
}
43+
44+
public static Set<String> methodThrowingException() throws Exception {
45+
throw new RuntimeException("testing");
46+
}
47+
}

sonar-python-plugin/src/test/java/org/sonar/plugins/python/PythonProfileTest.java

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
import static org.assertj.core.api.Assertions.assertThat;
2929
import static org.sonar.plugins.python.PythonProfile.SECURITY_RULES_CLASS_NAME;
3030
import static org.sonar.plugins.python.PythonProfile.SECURITY_RULE_KEYS_METHOD_NAME;
31-
import static org.sonar.plugins.python.PythonProfile.SECURITY_RULE_REPO_METHOD_NAME;
31+
import static org.sonar.plugins.python.PythonProfile.GET_REPOSITORY_KEY;
32+
import static org.sonar.plugins.python.PythonProfile.getDataflowBugDetectionRuleKeys;
33+
import static org.sonar.plugins.python.PythonProfile.getExternalRuleKeys;
3234
import static org.sonar.plugins.python.PythonProfile.getSecurityRuleKeys;
3335

3436
public class PythonProfileTest {
@@ -52,23 +54,42 @@ public void profile() {
5254
public void should_contains_security_rules_if_available() {
5355
// no security rule available
5456
PythonRules.getRuleKeys().clear();
55-
assertThat(getSecurityRuleKeys(SECURITY_RULES_CLASS_NAME, SECURITY_RULE_KEYS_METHOD_NAME, SECURITY_RULE_REPO_METHOD_NAME))
57+
assertThat(getSecurityRuleKeys())
5658
.isEmpty();
5759

5860
// one security rule available
5961
PythonRules.getRuleKeys().add("S3649");
60-
assertThat(getSecurityRuleKeys(SECURITY_RULES_CLASS_NAME, SECURITY_RULE_KEYS_METHOD_NAME, SECURITY_RULE_REPO_METHOD_NAME))
62+
assertThat(getSecurityRuleKeys())
6163
.containsOnly(RuleKey.of("pythonsecurity", "S3649"));
6264

63-
// invalid class name
64-
assertThat(getSecurityRuleKeys("xxx", SECURITY_RULE_KEYS_METHOD_NAME, SECURITY_RULE_REPO_METHOD_NAME)).isEmpty();
65+
PythonRules.throwOnCall = true;
66+
assertThat(getSecurityRuleKeys())
67+
.isEmpty();
68+
PythonRules.throwOnCall = false;
69+
}
6570

66-
// invalid method name
67-
assertThat(getSecurityRuleKeys(SECURITY_RULES_CLASS_NAME, "xxx", SECURITY_RULE_REPO_METHOD_NAME)).isEmpty();
71+
@Test
72+
public void should_contains_dataflow_bug_detection_rules_if_available() {
73+
// no dataflow bug detection rules available
74+
com.sonarsource.plugins.dbd.api.PythonRules.getDataflowBugDetectionRuleKeys().clear();
75+
assertThat(getDataflowBugDetectionRuleKeys()).isEmpty();
6876

69-
PythonRules.throwOnCall = true;
70-
assertThat(getSecurityRuleKeys(SECURITY_RULES_CLASS_NAME, SECURITY_RULE_KEYS_METHOD_NAME, SECURITY_RULE_REPO_METHOD_NAME))
77+
// one dataflow bug detection rule available
78+
com.sonarsource.plugins.dbd.api.PythonRules.getDataflowBugDetectionRuleKeys().add("S2259");
79+
assertThat(getDataflowBugDetectionRuleKeys()).containsOnly(RuleKey.of("dbd-repo-key", "S2259"));
80+
81+
com.sonarsource.plugins.dbd.api.PythonRules.throwOnCall = true;
82+
assertThat(getDataflowBugDetectionRuleKeys())
7183
.isEmpty();
7284
PythonRules.throwOnCall = false;
7385
}
86+
87+
@Test
88+
public void test_get_external_rule_keys() {
89+
// invalid class name
90+
assertThat(getExternalRuleKeys("xxx", SECURITY_RULE_KEYS_METHOD_NAME, GET_REPOSITORY_KEY)).isEmpty();
91+
92+
// invalid method name
93+
assertThat(getExternalRuleKeys(SECURITY_RULES_CLASS_NAME, "xxx", GET_REPOSITORY_KEY)).isEmpty();
94+
}
7495
}

0 commit comments

Comments
 (0)