Skip to content

Commit e917bf9

Browse files
authored
SONARPY-2462: Parallelize the qa_plugin tests (#2248)
1 parent 851f561 commit e917bf9

19 files changed

+124
-96
lines changed

its/plugin/it-python-plugin-test/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
<artifactId>maven-surefire-plugin</artifactId>
6464
<configuration>
6565
<includes>
66-
<include>com/sonar/python/it/plugin/TestSuite.java</include>
66+
<include>com/sonar/python/it/plugin/*.java</include>
6767
</includes>
6868
</configuration>
6969
</plugin>

its/plugin/it-python-plugin-test/src/test/java/com/sonar/python/it/plugin/BanditReportTest.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
*/
1717
package com.sonar.python.it.plugin;
1818

19-
import com.sonar.orchestrator.build.SonarScanner;
20-
import com.sonar.orchestrator.junit5.OrchestratorExtension;
2119
import java.io.File;
2220
import java.util.List;
2321
import org.junit.jupiter.api.Test;
@@ -33,14 +31,14 @@ class BanditReportTest {
3331
private static final String PROJECT = "bandit_project";
3432

3533
@RegisterExtension
36-
public static final OrchestratorExtension ORCHESTRATOR = TestsUtils.ORCHESTRATOR;
34+
public static final ConcurrentOrchestratorExtension ORCHESTRATOR = TestsUtils.ORCHESTRATOR;
3735

3836
@Test
3937
void import_report() {
4038
ORCHESTRATOR.getServer().provisionProject(PROJECT, PROJECT);
4139
ORCHESTRATOR.getServer().associateProjectToQualityProfile(PROJECT, "py", "no_rule");
4240
ORCHESTRATOR.executeBuild(
43-
SonarScanner.create()
41+
ORCHESTRATOR.createSonarScanner()
4442
.setProjectDir(new File("projects/bandit_project")));
4543

4644
List<Issues.Issue> issues = issues(PROJECT);

its/plugin/it-python-plugin-test/src/test/java/com/sonar/python/it/plugin/CPDTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package com.sonar.python.it.plugin;
1818

1919
import com.sonar.orchestrator.build.SonarScanner;
20-
import com.sonar.orchestrator.junit5.OrchestratorExtension;
2120
import java.io.File;
2221
import org.assertj.core.data.Offset;
2322
import org.junit.jupiter.api.BeforeAll;
@@ -41,13 +40,13 @@ class CPDTest {
4140
private static final String DUPLICATED_LINES_DENSITY = "duplicated_lines_density";
4241

4342
@RegisterExtension
44-
public static final OrchestratorExtension ORCHESTRATOR = TestsUtils.ORCHESTRATOR;
43+
public static final ConcurrentOrchestratorExtension ORCHESTRATOR = TestsUtils.ORCHESTRATOR;
4544

4645
@BeforeAll
4746
static void startServer() {
4847
ORCHESTRATOR.getServer().provisionProject(PROJECT_KEY, PROJECT_KEY);
4948
ORCHESTRATOR.getServer().associateProjectToQualityProfile(PROJECT_KEY, "py", "no_rule");
50-
SonarScanner build = SonarScanner.create()
49+
SonarScanner build = ORCHESTRATOR.createSonarScanner()
5150
.setProjectDir(new File("projects/cpd"))
5251
.setProjectKey(PROJECT_KEY)
5352
.setProjectName(PROJECT_KEY)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* SonarQube Python Plugin
3+
* Copyright (C) 2012-2024 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 Sonar Source-Available License Version 1, as published by SonarSource SA.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
* See the Sonar Source-Available License for more details.
13+
*
14+
* You should have received a copy of the Sonar Source-Available License
15+
* along with this program; if not, see https://sonarsource.com/license/ssal/
16+
*/
17+
package com.sonar.python.it.plugin;
18+
19+
import com.sonar.orchestrator.Orchestrator;
20+
import com.sonar.orchestrator.OrchestratorBuilder;
21+
import com.sonar.orchestrator.build.SonarScanner;
22+
import com.sonar.orchestrator.build.SonarScannerInstaller;
23+
import com.sonar.orchestrator.config.Configuration;
24+
import com.sonar.orchestrator.container.SonarDistribution;
25+
import com.sonar.orchestrator.server.StartupLogWatcher;
26+
import com.sonar.orchestrator.util.System2;
27+
import com.sonar.orchestrator.version.Version;
28+
import java.util.concurrent.CountDownLatch;
29+
import java.util.concurrent.atomic.AtomicInteger;
30+
import org.jetbrains.annotations.Nullable;
31+
import org.junit.jupiter.api.extension.BeforeAllCallback;
32+
import org.junit.jupiter.api.extension.ExtensionContext;
33+
34+
public class ConcurrentOrchestratorExtension extends Orchestrator implements BeforeAllCallback {
35+
private static final AtomicInteger REQUESTED_ORCHESTRATORS_KEY = new AtomicInteger();
36+
private static final CountDownLatch IS_ORCHESTRATOR_READY = new CountDownLatch(1);
37+
38+
ConcurrentOrchestratorExtension(Configuration config, SonarDistribution distribution, @Nullable StartupLogWatcher startupLogWatcher) {
39+
super(config, distribution, startupLogWatcher);
40+
}
41+
42+
@Override
43+
public void beforeAll(ExtensionContext context) throws InterruptedException {
44+
if (REQUESTED_ORCHESTRATORS_KEY.getAndIncrement() == 0) {
45+
start();
46+
47+
new SonarScannerInstaller(getConfiguration().locators()).install(Version.create(SonarScanner.DEFAULT_SCANNER_VERSION), getConfiguration().fileSystem().workspace());
48+
IS_ORCHESTRATOR_READY.countDown();
49+
50+
} else {
51+
IS_ORCHESTRATOR_READY.await();
52+
}
53+
}
54+
55+
56+
public SonarScanner createSonarScanner() {
57+
return SonarScanner.create();
58+
}
59+
60+
public static ConcurrentOrchestratorExtensionBuilder builderEnv() {
61+
return new ConcurrentOrchestratorExtensionBuilder(Configuration.createEnv());
62+
}
63+
64+
public static class ConcurrentOrchestratorExtensionBuilder extends OrchestratorBuilder<ConcurrentOrchestratorExtensionBuilder, ConcurrentOrchestratorExtension> {
65+
ConcurrentOrchestratorExtensionBuilder(Configuration initialConfig) {
66+
this(initialConfig, System2.INSTANCE);
67+
}
68+
69+
ConcurrentOrchestratorExtensionBuilder(Configuration initialConfig, System2 system2) {
70+
super(initialConfig, system2);
71+
}
72+
73+
@Override
74+
protected ConcurrentOrchestratorExtension build(Configuration finalConfig, SonarDistribution distribution, StartupLogWatcher startupLogWatcher) {
75+
return new ConcurrentOrchestratorExtension(finalConfig, distribution, startupLogWatcher);
76+
}
77+
}
78+
}

its/plugin/it-python-plugin-test/src/test/java/com/sonar/python/it/plugin/CoverageTest.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import com.google.common.collect.ImmutableMap.Builder;
2121
import com.sonar.orchestrator.build.BuildResult;
2222
import com.sonar.orchestrator.build.SonarScanner;
23-
import com.sonar.orchestrator.junit5.OrchestratorExtension;
2423
import java.io.File;
2524
import java.util.HashMap;
2625
import java.util.Map;
@@ -33,7 +32,7 @@ class CoverageTest {
3332

3433
private static final String COVERAGE_PROJECT = "projects/coverage_project";
3534
@RegisterExtension
36-
public static final OrchestratorExtension ORCHESTRATOR = TestsUtils.ORCHESTRATOR;
35+
public static final ConcurrentOrchestratorExtension ORCHESTRATOR = TestsUtils.ORCHESTRATOR;
3736

3837
private static final String PROJECT_KEY = "coverage_project";
3938
private static final String LINES_TO_COVER = "lines_to_cover";
@@ -55,7 +54,7 @@ void basic_coverage_reports_with_windows_paths() {
5554
}
5655

5756
private static void basicCoverageReports(String utReportPath) {
58-
SonarScanner build = SonarScanner.create()
57+
SonarScanner build = ORCHESTRATOR.createSonarScanner()
5958
.setProjectDir(new File(COVERAGE_PROJECT))
6059
.setProperty(DEPRECATED_COVERAGE_REPORT_PATH, "someReport")
6160
.setProperty(COVERAGE_REPORT_PATHS, utReportPath+",it-coverage1.xml,it-coverage2.xml");
@@ -75,7 +74,7 @@ private static void basicCoverageReports(String utReportPath) {
7574

7675
@Test
7776
void default_values() {
78-
SonarScanner build = SonarScanner.create()
77+
SonarScanner build = ORCHESTRATOR.createSonarScanner()
7978
.setProjectDir(new File(COVERAGE_PROJECT));
8079
ORCHESTRATOR.executeBuild(build);
8180

@@ -90,7 +89,7 @@ void default_values() {
9089

9190
@Test
9291
void empty_property() {
93-
SonarScanner build = SonarScanner.create()
92+
SonarScanner build = ORCHESTRATOR.createSonarScanner()
9493
.setProjectDir(new File(COVERAGE_PROJECT))
9594
.setProperty(DEPRECATED_COVERAGE_REPORT_PATH, "")
9695
.setProperty(COVERAGE_REPORT_PATHS, "");
@@ -106,7 +105,7 @@ void empty_property() {
106105

107106
@Test
108107
void empty_coverage_report() {
109-
SonarScanner build = SonarScanner.create()
108+
SonarScanner build = ORCHESTRATOR.createSonarScanner()
110109
.setProjectDir(new File(COVERAGE_PROJECT))
111110
.setProperty(DEPRECATED_COVERAGE_REPORT_PATH, EMPTY_XML)
112111
.setProperty(COVERAGE_REPORT_PATHS, EMPTY_XML);

its/plugin/it-python-plugin-test/src/test/java/com/sonar/python/it/plugin/CustomRulesExampleTest.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,32 +17,33 @@
1717
package com.sonar.python.it.plugin;
1818

1919
import com.sonar.orchestrator.build.SonarScanner;
20-
import com.sonar.orchestrator.junit5.OrchestratorExtension;
2120
import java.io.File;
2221
import java.util.List;
2322
import org.junit.jupiter.api.BeforeAll;
2423
import org.junit.jupiter.api.Test;
2524
import org.junit.jupiter.api.extension.RegisterExtension;
25+
import org.junit.jupiter.api.parallel.ResourceLock;
2626
import org.sonarqube.ws.Issues;
2727
import org.sonarqube.ws.client.issues.SearchRequest;
2828

2929
import static com.sonar.python.it.plugin.TestsUtils.newWsClient;
3030
import static java.util.Collections.singletonList;
3131
import static org.assertj.core.api.Assertions.assertThat;
3232

33+
@ResourceLock("project/custom_rules")
3334
class CustomRulesExampleTest {
3435

3536
@RegisterExtension
36-
public static final OrchestratorExtension orchestrator = TestsUtils.ORCHESTRATOR;
37+
public static final ConcurrentOrchestratorExtension orchestrator = TestsUtils.ORCHESTRATOR;
3738

38-
private static final String PROJECT_KEY = "custom-rules";
39-
private static final String PROJECT_NAME = "Custom Rules";
39+
private static final String PROJECT_KEY = "custom-rules-example";
40+
private static final String PROJECT_NAME = "Custom Rules Example";
4041

4142
@BeforeAll
4243
static void prepare() {
4344
orchestrator.getServer().provisionProject(PROJECT_KEY, PROJECT_NAME);
4445
orchestrator.getServer().associateProjectToQualityProfile(PROJECT_KEY, "py", "python-custom-rules-example-profile");
45-
SonarScanner build = SonarScanner.create()
46+
SonarScanner build = orchestrator.createSonarScanner()
4647
.setProjectDir(new File("projects/custom_rules"))
4748
.setProjectKey(PROJECT_KEY)
4849
.setProjectName(PROJECT_NAME)

its/plugin/it-python-plugin-test/src/test/java/com/sonar/python/it/plugin/CustomRulesTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,24 @@
1717
package com.sonar.python.it.plugin;
1818

1919
import com.sonar.orchestrator.build.SonarScanner;
20-
import com.sonar.orchestrator.junit5.OrchestratorExtension;
2120
import java.io.File;
2221
import java.util.List;
2322
import org.junit.jupiter.api.BeforeAll;
2423
import org.junit.jupiter.api.Test;
2524
import org.junit.jupiter.api.extension.RegisterExtension;
25+
import org.junit.jupiter.api.parallel.ResourceLock;
2626
import org.sonarqube.ws.Issues;
2727
import org.sonarqube.ws.client.issues.SearchRequest;
2828

2929
import static com.sonar.python.it.plugin.TestsUtils.newWsClient;
3030
import static java.util.Collections.singletonList;
3131
import static org.assertj.core.api.Assertions.assertThat;
3232

33+
@ResourceLock("project/custom_rules")
3334
class CustomRulesTest {
3435

3536
@RegisterExtension
36-
public static final OrchestratorExtension orchestrator = TestsUtils.ORCHESTRATOR;
37+
public static final ConcurrentOrchestratorExtension orchestrator = TestsUtils.ORCHESTRATOR;
3738

3839
private static final String PROJECT_KEY = "custom-rules";
3940
private static final String PROJECT_NAME = "Custom Rules";
@@ -42,7 +43,7 @@ class CustomRulesTest {
4243
static void prepare() {
4344
orchestrator.getServer().provisionProject(PROJECT_KEY, PROJECT_NAME);
4445
orchestrator.getServer().associateProjectToQualityProfile(PROJECT_KEY, "py", "python-custom-rules-profile");
45-
SonarScanner build = SonarScanner.create()
46+
SonarScanner build = orchestrator.createSonarScanner()
4647
.setProjectDir(new File("projects/custom_rules"))
4748
.setProjectKey(PROJECT_KEY)
4849
.setProjectName(PROJECT_NAME)

its/plugin/it-python-plugin-test/src/test/java/com/sonar/python/it/plugin/Flake8ReportTest.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
*/
1717
package com.sonar.python.it.plugin;
1818

19-
import com.sonar.orchestrator.build.SonarScanner;
20-
import com.sonar.orchestrator.junit5.OrchestratorExtension;
2119
import java.io.File;
2220
import java.util.List;
2321
import org.junit.jupiter.api.Test;
@@ -33,14 +31,14 @@ class Flake8ReportTest {
3331
private static final String PROJECT = "flake8_project";
3432

3533
@RegisterExtension
36-
public static final OrchestratorExtension ORCHESTRATOR = TestsUtils.ORCHESTRATOR;
34+
public static final ConcurrentOrchestratorExtension ORCHESTRATOR = TestsUtils.ORCHESTRATOR;
3735

3836
@Test
3937
void import_report() {
4038
ORCHESTRATOR.getServer().provisionProject(PROJECT, PROJECT);
4139
ORCHESTRATOR.getServer().associateProjectToQualityProfile(PROJECT, "py", "no_rule");
4240
ORCHESTRATOR.executeBuild(
43-
SonarScanner.create()
41+
ORCHESTRATOR.createSonarScanner()
4442
.setProjectDir(new File("projects/flake8_project")));
4543

4644
List<Issues.Issue> issues = issues(PROJECT);

its/plugin/it-python-plugin-test/src/test/java/com/sonar/python/it/plugin/MetricsTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import com.sonar.orchestrator.build.BuildResult;
2020
import com.sonar.orchestrator.build.SonarScanner;
21-
import com.sonar.orchestrator.junit5.OrchestratorExtension;
2221
import java.io.File;
2322
import org.assertj.core.data.Offset;
2423
import org.junit.jupiter.api.BeforeAll;
@@ -56,15 +55,15 @@ class MetricsTest {
5655
private static final Offset<Double> OFFSET = Offset.offset(0.01d);
5756

5857
@RegisterExtension
59-
public static final OrchestratorExtension orchestrator = TestsUtils.ORCHESTRATOR;
58+
public static final ConcurrentOrchestratorExtension orchestrator = TestsUtils.ORCHESTRATOR;
6059

6160
private static BuildResult buildResult;
6261

6362
@BeforeAll
6463
static void startServer() {
6564
orchestrator.getServer().provisionProject(PROJECT_KEY, PROJECT_KEY);
6665
orchestrator.getServer().associateProjectToQualityProfile(PROJECT_KEY, "py", "no_rule");
67-
SonarScanner build = SonarScanner.create()
66+
SonarScanner build = orchestrator.createSonarScanner()
6867
.setProjectDir(new File("projects/metrics"))
6968
.setProjectKey(PROJECT_KEY)
7069
.setProjectName(PROJECT_KEY)

its/plugin/it-python-plugin-test/src/test/java/com/sonar/python/it/plugin/MypyReportTest.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
*/
1717
package com.sonar.python.it.plugin;
1818

19-
import com.sonar.orchestrator.build.SonarScanner;
20-
import com.sonar.orchestrator.junit5.OrchestratorExtension;
2119
import java.io.File;
2220
import java.util.List;
2321
import org.junit.jupiter.api.Test;
@@ -33,14 +31,14 @@ class MypyReportTest {
3331
private static final String PROJECT = "mypy_project";
3432

3533
@RegisterExtension
36-
public static final OrchestratorExtension ORCHESTRATOR = TestsUtils.ORCHESTRATOR;
34+
public static final ConcurrentOrchestratorExtension ORCHESTRATOR = TestsUtils.ORCHESTRATOR;
3735

3836
@Test
3937
void import_report() {
4038
ORCHESTRATOR.getServer().provisionProject(PROJECT, PROJECT);
4139
ORCHESTRATOR.getServer().associateProjectToQualityProfile(PROJECT, "py", "no_rule");
4240
ORCHESTRATOR.executeBuild(
43-
SonarScanner.create()
41+
ORCHESTRATOR.createSonarScanner()
4442
.setProjectDir(new File("projects/mypy_project")));
4543

4644
List<Issues.Issue> issues = issues(PROJECT);

0 commit comments

Comments
 (0)