Skip to content

Commit

Permalink
SONARPY-2429: Merge the ruling and the extended ruling (#2232)
Browse files Browse the repository at this point in the history
  • Loading branch information
Seppli11 committed Dec 13, 2024
1 parent a090b60 commit 3839043
Show file tree
Hide file tree
Showing 2,429 changed files with 331,681 additions and 74 deletions.
23 changes: 0 additions & 23 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -184,29 +184,6 @@ ruling_task:
- mvn verify -Dsonar.runtimeVersion=LATEST_RELEASE -Dmaven.test.redirectTestOutputToFile=false -B -e -V -Dtest=PythonRulingTest
cleanup_before_cache_script: cleanup_maven_repository

extended_ruling_task:
depends_on:
- build
<<: *ONLY_SONARSOURCE_QA
eks_container:
<<: *QA_CONTAINER_DEFINITION
cpu: 4
memory: 8G
env:
CIRRUS_CLONE_DEPTH: 10
SONARSOURCE_QA: true
maven_cache:
folder: ${CIRRUS_WORKING_DIR}/.m2/repository
<<: *ORCHESTRATOR_CACHE_DEFINITION
submodules_script:
- git submodule update --init
ruling_script:
- source cirrus-env QA
- source set_maven_build_version $BUILD_NUMBER
- cd its/ruling
- mvn verify -Dsonar.runtimeVersion=LATEST_RELEASE -Dmaven.test.redirectTestOutputToFile=false -B -e -V -Dtest=PythonExtendedRulingTest
cleanup_before_cache_script: cleanup_maven_repository

pr_analysis_qa_task:
depends_on:
- build
Expand Down
12 changes: 6 additions & 6 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[submodule "its/sources"]
path = its/sources
[submodule "its/sources_ruling"]
path = its/sources_ruling
url = https://github.com/SonarCommunity/python-test-sources.git
[submodule "its/sources_extended"]
path = its/sources_extended
url = https://github.com/SonarCommunity/python-test-sources.git
branch = extended
branch = master-temp
shallow = true
[submodule "tools/typeshed_serializer/resources/typeshed"]
path = python-frontend/typeshed_serializer/resources/typeshed
url = https://github.com/python/typeshed.git
shallow = true
[submodule "tools/typeshed_serializer/resources/python-type-stubs"]
path = python-frontend/typeshed_serializer/resources/python-type-stubs
url = https://github.com/microsoft/python-type-stubs
shallow = true
285 changes: 242 additions & 43 deletions its/ruling/src/test/java/org/sonar/python/it/PythonRulingTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,26 @@
import com.sonar.orchestrator.junit5.OrchestratorExtension;
import com.sonar.orchestrator.locator.FileLocation;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.sonarqube.ws.Issues;
import org.sonarqube.ws.client.HttpConnector;
import org.sonarqube.ws.client.WsClient;
import org.sonarqube.ws.client.WsClientFactories;
import org.sonarqube.ws.client.issues.SearchRequest;
import org.sonarsource.analyzer.commons.ProfileGenerator;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.python.it.RulingHelper.getOrchestrator;

// Ruling test for bug rules, to ensure they are properly tested without slowing down the CI
class PythonRulingTest {

public static final String PROJECT_KEY = "project";

@RegisterExtension
public static final OrchestratorExtension ORCHESTRATOR = getOrchestrator();

private static final String PROFILE_NAME = "rules";

@BeforeAll
static void prepare_quality_profile() {
ProfileGenerator.RulesConfiguration parameters = new ProfileGenerator.RulesConfiguration()
Expand All @@ -59,47 +53,252 @@ static void prepare_quality_profile() {
}

@Test
void test() throws Exception {
ORCHESTRATOR.getServer().provisionProject(PROJECT_KEY, PROJECT_KEY);
ORCHESTRATOR.getServer().associateProjectToQualityProfile(PROJECT_KEY, "py", "rules");
ORCHESTRATOR.getServer().associateProjectToQualityProfile(PROJECT_KEY, "ipynb", "rules");
File litsDifferencesFile = FileLocation.of("target/differences").getFile();
SonarScanner build = SonarScanner.create(FileLocation.of("../sources").getFile())
.setProjectKey(PROJECT_KEY)
.setProjectName(PROJECT_KEY)
.setProjectVersion("1")
.setSourceEncoding("UTF-8")
.setSourceDirs(".")
.setProperty("sonar.lits.dump.old", FileLocation.of("src/test/resources/expected").getFile().getAbsolutePath())
.setProperty("sonar.lits.dump.new", FileLocation.of("target/actual").getFile().getAbsolutePath())
.setProperty("sonar.cpd.exclusions", "**/*")
.setProperty("sonar.lits.differences", litsDifferencesFile.getAbsolutePath())
.setProperty("sonar.internal.analysis.failFast", "true")
.setEnvironmentVariable("SONAR_RUNNER_OPTS", "-Xmx2000m");
ORCHESTRATOR.executeBuild(build);
void test_airflow() throws IOException {
SonarScanner build = buildWithCommonProperties("airflow");
build.setProperty("sonar.sources", "airflow");
build.setProperty("sonar.tests", "tests");
executeBuild(build);
}

@Test
void test_archery() throws IOException {
executeBuild(buildWithCommonProperties("Archery"));
}

String issueDifferences = issues(PROJECT_KEY).stream()
.map(i -> String.join("\t", i.getRule(), "" + i.getSeverity(), i.getComponent(), "" + i.getLine()))
.collect(Collectors.joining("\n"));
assertThat(issueDifferences).isEmpty();
@Test
void test_autokeras() throws IOException {
executeBuild(buildWithCommonProperties("autokeras"));
}

String litsDifferences = new String(Files.readAllBytes(litsDifferencesFile.toPath()), UTF_8);
assertThat(litsDifferences).isEmpty();
@Test
void test_biopython() throws IOException {
executeBuild(buildWithCommonProperties("biopython"));
}

@Test
void test_black() throws IOException {
SonarScanner build = buildWithCommonProperties("black");
build.setProperty("sonar.sources", "src");
build.setProperty("sonar.tests", "tests");
build.setProperty("sonar.test.exclusions", "tests/data/async_as_identifier.py");
executeBuild(build);
}

@Test
void test_buildbot() throws IOException {
SonarScanner build = buildWithCommonProperties("buildbot","buildbot-0.8.6p1");
build.setProperty("sonar.sources", "buildbot");
build.setProperty("sonar.tests", "contrib");
executeBuild(build);
}

@Test
void test_buildbot_slave() throws IOException {
SonarScanner build = buildWithCommonProperties("buildbot-slave", "buildbot-slave-0.8.6p1");
build.setProperty("sonar.sources", "buildslave");
build.setProperty("sonar.tests", "contrib");
executeBuild(build);
}

@Test
void test_calibre() throws IOException {
SonarScanner build = buildWithCommonProperties("calibre");
build.setProperty("sonar.sources", "src");
executeBuild(build);
}

@Test
void test_celery() throws IOException {
SonarScanner build = buildWithCommonProperties("celery");
build.setProperty("sonar.sources", "celery");
build.setProperty("sonar.tests", "t");
executeBuild(build);
}

@Test
void test_chalice() throws IOException {
SonarScanner build = buildWithCommonProperties("chalice");
build.setProperty("sonar.sources", "chalice");
build.setProperty("sonar.tests", "tests");
executeBuild(build);
}

@Test
void test_django() throws IOException {
SonarScanner build = buildWithCommonProperties("django", "django-2.2.3");
build.setProperty("sonar.sources", "django");
executeBuild(build);
}

@Test
void test_django_cms() throws IOException {
SonarScanner build = buildWithCommonProperties("django-cms", "django-cms-3.7.1");
build.setProperty("sonar.sources", "cms");
build.setProperty("sonar.test", "cms/tests");
executeBuild(build);
}

@Test
void test_django_shop() throws IOException {
SonarScanner build = buildWithCommonProperties("django-shop");
build.setProperty("sonar.sources", "shop");
build.setProperty("sonar.tests", "tests");
executeBuild(build);
}

@Test
void test_docker_compose() throws IOException {
SonarScanner build = buildWithCommonProperties("docker-compose", "docker-compose-1.24.1");
build.setProperty("sonar.sources", "compose");
build.setProperty("sonar.tests", "tests");
executeBuild(build);
}

@Test
void test_indico() throws IOException {
SonarScanner build = buildWithCommonProperties("indico");
build.setProperty("sonar.sources", "indico");
executeBuild(build);
}

static WsClient newWsClient() {
return newWsClient(null, null);
@Test
void test_keras_tutorials() throws IOException {
executeBuild(buildWithCommonProperties("keras-tutorials"));
}

@Test
void test_LibCST() throws IOException {
SonarScanner build = buildWithCommonProperties("LibCST");
build.setProperty("sonar.sources", "libcst");
build.setProperty("sonar.tests", "libcst/tests");
build.setProperty("sonar.test.inclusions", "**/");
executeBuild(build);
}

@Test
void test_mypy() throws IOException {
SonarScanner build = buildWithCommonProperties("mypy", "mypy-0.782");
build.setProperty("sonar.sources", "mypy,mypyc");
build.setProperty("sonar.exclusions", "**/test/**/*");
build.setProperty("sonar.tests", "mypy/test,mypyc/test");
executeBuild(build);
}

@Test
void test_nltk() throws IOException {
SonarScanner build = buildWithCommonProperties("nltk");
build.setProperty("sonar.sources", ".");
build.setProperty("sonar.exclusions", "**/test/**/*");
executeBuild(build);
}

@Test
void test_numpy() throws IOException {
SonarScanner build = buildWithCommonProperties("numpy", "numpy-1.16.4");
build.setProperty("sonar.sources", "numpy");
build.setProperty("sonar.exclusions", "**/tests/**/*");
build.setProperty("sonar.tests", "numpy/tests");
executeBuild(build);
}

@Test
void test_pecos() throws IOException {
SonarScanner build = buildWithCommonProperties("pecos");
build.setProperty("sonar.sources", "pecos");
build.setProperty("sonar.tests", "test");
executeBuild(build);
}

@Test
void test_saleor() throws IOException {
SonarScanner build = buildWithCommonProperties("saleor");
build.setProperty("sonar.sources", "saleor");
executeBuild(build);
}

@Test
void test_salt() throws IOException {
SonarScanner build = buildWithCommonProperties("salt");
// salt is not actually a Python 3.12 project. This is to ensure analysis is performed correctly when the parameter is set.
build.setProperty("sonar.python.version", "3.12");
build.setProperty("sonar.sources", "salt");
build.setProperty("sonar.tests", "tests");
executeBuild(build);
}

@Test
void test_scikit_learn() throws IOException {
SonarScanner build = buildWithCommonProperties("scikit-learn");
build.setProperty("sonar.sources", "sklearn");
executeBuild(build);
}

@Test
void test_specific_rules() throws IOException {
// this tests is a hodgepodge of tests which are designed for specific rules
executeBuild(buildWithCommonProperties("specific-rules"));
}

@Test
void test_tensorflow() throws IOException {
SonarScanner build = buildWithCommonProperties("tensorflow");
build.setProperty("sonar.sources", "python");
executeBuild(build);
}

@Test
void test_timesketch() throws IOException {
SonarScanner build = buildWithCommonProperties("timesketch");
build.setProperty("sonar.sources", "timesketch");
build.setProperty("sonar.test.inclusions", "**/*_test.py");
executeBuild(build);
}

@Test
void test_tornado() throws IOException {
SonarScanner build = buildWithCommonProperties("tornado", "tornado-2.3");
build.setProperty("sonar.sources", "tornado");
build.setProperty("sonar.exclusions", "**/test/**/*");
build.setProperty("sonar.tests", "tornado/test");
executeBuild(build);
}

@Test
void test_twisted() throws IOException {
SonarScanner build = buildWithCommonProperties("twisted", "twisted-12.1.0");
build.setProperty("sonar.sources", "twisted");
build.setProperty("sonar.exclusions", "**/test/**/*");
build.setProperty("sonar.tests", "twisted/test");
executeBuild(build);
}

static WsClient newWsClient(String login, String password) {
return WsClientFactories.getDefault().newClient(HttpConnector.newBuilder()
.url(ORCHESTRATOR.getServer().getUrl())
.credentials(login, password)
.build());

public SonarScanner buildWithCommonProperties(String projectKey) {
return buildWithCommonProperties(projectKey, projectKey);
}

static List<Issues.Issue> issues(String projectKey) {
return newWsClient().issues().search(new SearchRequest().setProjects(singletonList(projectKey))).getIssuesList();
public SonarScanner buildWithCommonProperties(String projectKey, String projectName) {
ORCHESTRATOR.getServer().provisionProject(projectKey, projectKey);
ORCHESTRATOR.getServer().associateProjectToQualityProfile(projectKey, "py", PROFILE_NAME);
ORCHESTRATOR.getServer().associateProjectToQualityProfile(projectKey, "ipynb", PROFILE_NAME);
return SonarScanner.create(FileLocation.of(String.format("../sources_ruling/%s", projectName)).getFile())
.setProjectKey(projectKey)
.setProjectName(projectKey)
.setProjectVersion("1")
.setSourceEncoding("UTF-8")
.setSourceDirs(".")
.setProperty("sonar.lits.dump.old", FileLocation.of(String.format("src/test/resources/expected_ruling/%s", projectKey)).getFile().getAbsolutePath())
.setProperty("sonar.lits.dump.new", FileLocation.of(String.format("target/actual_ruling/%s", projectKey)).getFile().getAbsolutePath())
.setProperty("sonar.cpd.exclusions", "**/*")
.setProperty("sonar.internal.analysis.failFast", "true")
.setEnvironmentVariable("SONAR_RUNNER_OPTS", "-Xmx2000m");
}

void executeBuild(SonarScanner build) throws IOException {
File litsDifferencesFile = FileLocation.of("target/differences").getFile();
build.setProperty("sonar.lits.differences", litsDifferencesFile.getAbsolutePath());
ORCHESTRATOR.executeBuild(build);
String litsDifferences = new String(Files.readAllBytes(litsDifferencesFile.toPath()), UTF_8);
assertThat(litsDifferences).isEmpty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"biopython:Bio/Nexus/Nexus.py": [
629
],
"biopython:Bio/Nexus/Trees.py": [
45
],
"biopython:Bio/PDB/internal_coords.py": [
1129
]
}
Loading

0 comments on commit 3839043

Please sign in to comment.