Skip to content

Commit c733600

Browse files
SONARPY-935 Ensure there are no deprecated rules in the default quality profile (#1046)
* SONARPY-935 Ensure there are no deprecated rules in the default quality profile * Add test to ensure locally deprecated keys stay deprecated
1 parent 5f7804b commit c733600

File tree

3 files changed

+88
-5
lines changed

3 files changed

+88
-5
lines changed

python-checks/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@
5252
<artifactId>guava</artifactId>
5353
<scope>test</scope>
5454
</dependency>
55+
<dependency>
56+
<groupId>org.sonarsource.analyzer-commons</groupId>
57+
<artifactId>sonar-analyzer-commons</artifactId>
58+
<scope>test</scope>
59+
</dependency>
5560
</dependencies>
5661

5762
</project>

python-checks/src/main/resources/org/sonar/l10n/py/rules/python/Sonar_way_profile.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
"S1313",
2929
"S1481",
3030
"S1515",
31-
"S1523",
3231
"S1542",
3332
"S1656",
3433
"S1700",
@@ -86,7 +85,6 @@
8685
"S4487",
8786
"S4502",
8887
"S4507",
89-
"S4721",
9088
"S4790",
9189
"S4792",
9290
"S4828",

python-checks/src/test/java/org/sonar/python/checks/CheckListTest.java

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,30 @@
2121

2222
import com.google.common.collect.Iterables;
2323
import java.io.File;
24+
import java.io.FileInputStream;
2425
import java.io.IOException;
26+
import java.io.InputStream;
27+
import java.io.InputStreamReader;
2528
import java.nio.file.Files;
2629
import java.nio.file.Path;
2730
import java.nio.file.Paths;
31+
import java.util.Arrays;
2832
import java.util.List;
33+
import java.util.Set;
2934
import java.util.regex.Matcher;
3035
import java.util.regex.Pattern;
3136
import java.util.stream.Collectors;
3237
import java.util.stream.Stream;
3338
import org.apache.commons.io.FileUtils;
3439
import org.junit.Test;
40+
import org.sonarsource.analyzer.commons.internal.json.simple.JSONArray;
41+
import org.sonarsource.analyzer.commons.internal.json.simple.JSONObject;
42+
import org.sonarsource.analyzer.commons.internal.json.simple.parser.JSONParser;
43+
import org.sonarsource.analyzer.commons.internal.json.simple.parser.ParseException;
3544

3645
import static java.nio.charset.StandardCharsets.UTF_8;
3746
import static org.assertj.core.api.Assertions.assertThat;
47+
import static org.assertj.core.api.Assertions.fail;
3848

3949
public class CheckListTest {
4050

@@ -48,7 +58,7 @@ public class CheckListTest {
4858
@Test
4959
public void count() {
5060
int count = 0;
51-
List<File> files = (List<File>) FileUtils.listFiles(new File("src/main/java/org/sonar/python/checks/"), new String[] {"java"}, true);
61+
List<File> files = (List<File>) FileUtils.listFiles(new File("src/main/java/org/sonar/python/checks/"), new String[]{"java"}, true);
5262
for (File file : files) {
5363
if (file.getName().endsWith("Check.java") && !file.getName().startsWith("Abstract")) {
5464
count++;
@@ -67,8 +77,8 @@ public void test() {
6777
for (Class cls : checks) {
6878
String testName = '/' + cls.getName().replace('.', '/') + "Test.class";
6979
assertThat(getClass().getResource(testName))
70-
.overridingErrorMessage("No test for " + cls.getSimpleName())
71-
.isNotNull();
80+
.overridingErrorMessage("No test for " + cls.getSimpleName())
81+
.isNotNull();
7282
}
7383
}
7484

@@ -94,6 +104,76 @@ public void validate_sqKey_field_in_json() throws IOException {
94104
}
95105
}
96106

107+
@Test
108+
public void test_no_deprecated_rule_in_default_profile() throws IOException, ParseException {
109+
try (Stream<Path> fileStream = Files.find(METADATA_DIR, 1, (path, attr) -> path.toString().endsWith(".json"))) {
110+
List<Path> jsonList = fileStream.collect(Collectors.toList());
111+
112+
Path sonarWayProfilePath = jsonList.stream().filter(path -> path.toString().endsWith("Sonar_way_profile.json")).findFirst().get();
113+
List<String> keysInDefaultProfile = getKeysInDefaultProfile(sonarWayProfilePath);
114+
115+
Set<String> deprecatedKeys = jsonList.stream()
116+
.filter(path -> !path.toString().endsWith("Sonar_way_profile.json"))
117+
.filter(path1 -> {
118+
try {
119+
return isDeprecated(path1);
120+
} catch (Exception e) {
121+
fail(String.format("Exception when deserializing JSON file \"%s\"", path1.getFileName().toString()));
122+
return false;
123+
}
124+
})
125+
.map(Path::getFileName)
126+
.map(Path::toString)
127+
.map(name -> name.replaceAll("\\.json$", ""))
128+
.collect(Collectors.toSet());
129+
130+
assertThat(keysInDefaultProfile).isNotEmpty();
131+
assertThat(deprecatedKeys).isNotEmpty();
132+
assertThat(keysInDefaultProfile).doesNotContainAnyElementsOf(deprecatedKeys);
133+
}
134+
}
135+
136+
@Test
137+
public void test_locally_deprecated_rules_stay_deprecated() throws IOException, ParseException {
138+
// Some rules have been deprecated only for Python. When executed, rule-api reverts those rule to "ready" status, which is incorrect.
139+
// This test is here to ensure it doesn't happen.
140+
List<String> locallyDeprecatedRules = Arrays.asList("S1523", "S4721");
141+
try (Stream<Path> fileStream = Files.find(METADATA_DIR, 1, (path, attr) -> path.toString().endsWith(".json"))) {
142+
Set<String> deprecatedKeys = fileStream
143+
.filter(path -> !path.toString().endsWith("Sonar_way_profile.json"))
144+
.filter(path1 -> {
145+
try {
146+
return isDeprecated(path1);
147+
} catch (Exception e) {
148+
fail(String.format("Exception when deserializing JSON file \"%s\"", path1.getFileName().toString()));
149+
return false;
150+
}
151+
})
152+
.map(Path::getFileName)
153+
.map(Path::toString)
154+
.map(name -> name.replaceAll("\\.json$", ""))
155+
.collect(Collectors.toSet());
156+
157+
assertThat(deprecatedKeys).containsAll(locallyDeprecatedRules);
158+
}
159+
}
160+
161+
private static boolean isDeprecated(Path path) throws IOException, ParseException {
162+
InputStream in = new FileInputStream(path.toFile());
163+
JSONParser jsonParser = new JSONParser();
164+
JSONObject ruleJson = (JSONObject) jsonParser.parse(new InputStreamReader(in, UTF_8));
165+
Object status = ruleJson.get("status");
166+
return status.equals("deprecated");
167+
}
168+
169+
private static List<String> getKeysInDefaultProfile(Path sonarWayPath) throws IOException, ParseException {
170+
InputStream in = new FileInputStream(sonarWayPath.toFile());
171+
JSONParser jsonParser = new JSONParser();
172+
JSONObject sonarWayJson = (JSONObject) jsonParser.parse(new InputStreamReader(in, UTF_8));
173+
JSONArray sonarWayKeys = (JSONArray) sonarWayJson.get("ruleKeys");
174+
return (List<String>) sonarWayKeys.stream().sorted().collect(Collectors.toList());
175+
}
176+
97177
private static String extractSqKey(Path jsonFile) {
98178
try {
99179
String content = new String(Files.readAllBytes(jsonFile), UTF_8);

0 commit comments

Comments
 (0)