Skip to content

Commit 25d1755

Browse files
SCANGRADLE-292 Fix locking issue with parallel execution in Android Gradle 9 projects (#391)
1. Fix README instructions for remote debugging 2. Add mainLibraries and testLibraries fields to ProjectProperties and SonarResolverTask 3. Resolve Android libraries at SonarResolverTask configuration time 4. Extract logic for getting the test variant in AndroidUtils 5. Fix case of android test libraries in configuration of resolver task 6. Use pre-resolved libraries from resolver files in SonarTask 7. Move code to get android libraries to AndroidUtils 8. Remove code that was handling older version of the API we no longer support 9. Add project with android and gradle9 10. Fix assumption messages that didn't make sense 11. Add end-to-end test for gradle 9 android project 12. Adjust lines of deprecation warnings because of changes in SonarResolverTask 13. Add IT test for AndroidUtils 14. Add test libraries assertions in AndroidTest Co-authored-by: Claude <[email protected]>
1 parent c918900 commit 25d1755

File tree

48 files changed

+1123
-60
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1123
-60
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ Run with:
106106
See the previous point about including the plugin's build when building a target project.
107107
To debug, simply add the parameter:
108108
```
109-
./gradlew sonar --include-build /path/to/sonar-scanner-gradle -Dorg.gradle.debug=true
109+
./gradlew sonar --include-build /path/to/sonar-scanner-gradle/build/classes/java/main/ -Dorg.gradle.debug=true
110110
```
111111

112112
Now debug remotely by connecting to the port 5005.

integrationTests/src/test/java/org/sonarqube/gradle/AbstractGradleIT.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ protected static Semver getGradleVersion() {
7676

7777
protected static void ignoreThisTestIfGradleVersionIsLessThan(String version) {
7878
Semver gradleVersion = getGradleVersion();
79-
Assume.assumeTrue("Test is ignored for Gradle version " + gradleVersion + " which is greater than or equal to ", gradleVersion.isGreaterThanOrEqualTo(version));
79+
Assume.assumeTrue("Test is ignored for Gradle version " + gradleVersion + " which should be greater than or equal to " + version, gradleVersion.isGreaterThanOrEqualTo(version));
8080
}
8181

8282
protected static void ignoreThisTestIfGradleVersionIsGreaterThanOrEqualTo(String version) {
8383
Semver gradleVersion = getGradleVersion();
84-
Assume.assumeTrue("Test is ignored for Gradle version " + gradleVersion + " which is greater than or equal to ", gradleVersion.isLowerThan(version));
84+
Assume.assumeTrue("Test is ignored for Gradle version " + gradleVersion + " which should be lower than " + version, gradleVersion.isLowerThan(version));
8585
}
8686

8787
protected static void ignoreThisTestIfGradleVersionIsNotBetween(String minVersionIncluded, String maxVersionExcluded) {
@@ -345,7 +345,7 @@ static void assertThatPluginDoesNotCreateGradleDeprecationWarnings(String text)
345345
}
346346

347347
static boolean isUnexpectedWarning(String line){
348-
if(line.contains("SonarResolverTask.java:108") || line.contains("SonarResolverTask.java:111")){
348+
if(line.contains("SonarResolverTask.java:128") || line.contains("SonarResolverTask.java:131")){
349349
// These warnings are expected until we properly support Gradle 9
350350
return false;
351351
}

integrationTests/src/test/java/org/sonarqube/gradle/AndroidTest.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.nio.file.Paths;
2525
import java.util.Arrays;
2626
import java.util.Collections;
27+
import java.util.Map;
2728
import java.util.Properties;
2829
import java.util.stream.Stream;
2930

@@ -447,6 +448,69 @@ public void testAndroidLintReport() throws Exception {
447448
assertThat(Paths.get(props.getProperty(":app2.sonar.androidLint.reportPaths"))).isEqualTo(baseDir.resolve("app2/build/reports/lint-results-debug.xml"));
448449
assertThat(props.getProperty(":app3.sonar.androidLint.reportPaths")).isEqualTo("/custom/path/to/report.xml");
449450
assertThat(Paths.get(props.getProperty(":app4.sonar.androidLint.reportPaths"))).isEqualTo(baseDir.resolve("app4/build/reports/lint-results-fullRelease.xml"));
451+
}
450452

453+
@Test
454+
public void gradle9AndroidParallelExample() throws Exception {
455+
ignoreThisTestIfGradleVersionIsLessThan("9.0.0");
456+
Map<String, String> env = Collections.emptyMap();
457+
Properties props = runGradlewSonarSimulationModeWithEnv("/android-gradle9", env, "--quiet", "--console=plain");
458+
Map<String, String> comparableProps = extractComparableProperties(props);
459+
460+
// Verify key project structure properties
461+
assertThat(comparableProps)
462+
.containsEntry("sonar.projectKey", "org.sonarqube:example-android-gradle-dynamic-module")
463+
.containsEntry("sonar.projectName", "Simple Android Gradle Project With Dynamic Module")
464+
.containsEntry("sonar.projectVersion", "unspecified")
465+
.containsEntry("sonar.modules", ":app,:javalib,:mydynamicfeature")
466+
.containsEntry("sonar.host.url", "https://sonarcloud.io");
467+
468+
// Verify :app module properties
469+
assertThat(comparableProps)
470+
.containsEntry(":app.sonar.android.detected", "true")
471+
.containsEntry(":app.sonar.java.source", "1.8")
472+
.containsEntry(":app.sonar.java.target", "1.8")
473+
.containsEntry(":app.sonar.moduleKey", "org.sonarqube:example-android-gradle-dynamic-module:app")
474+
.containsEntry(":app.sonar.projectName", "app");
475+
476+
// Verify :mydynamicfeature module properties
477+
assertThat(comparableProps)
478+
.containsEntry(":mydynamicfeature.sonar.android.detected", "true")
479+
.containsEntry(":mydynamicfeature.sonar.java.source", "1.8")
480+
.containsEntry(":mydynamicfeature.sonar.java.target", "1.8")
481+
.containsEntry(":mydynamicfeature.sonar.moduleKey", "org.sonarqube:example-android-gradle-dynamic-module:mydynamicfeature")
482+
.containsEntry(":mydynamicfeature.sonar.projectName", "mydynamicfeature");
483+
484+
// Verify Android libraries are resolved and present
485+
assertThat(comparableProps.get(":app.sonar.java.libraries"))
486+
.isNotEmpty()
487+
.contains("android.jar")
488+
.contains("core-lambda-stubs.jar");
489+
assertThat(comparableProps.get(":app.sonar.java.test.libraries"))
490+
.isNotEmpty()
491+
.contains("android.jar", "core-lambda-stubs.jar", "R.jar", "jetified-junit-4.13.2.jar", "jetified-hamcrest-core-1.3.jar", "jetified-junit-1.1.2-api.jar");
492+
493+
assertThat(comparableProps.get(":mydynamicfeature.sonar.java.libraries"))
494+
.isNotEmpty()
495+
.contains("android.jar");
496+
assertThat(comparableProps.get(":mydynamicfeature.sonar.java.test.libraries"))
497+
.isNotEmpty()
498+
.contains("android.jar", "core-lambda-stubs.jar", "R.jar", "jetified-junit-4.13.2.jar", "jetified-hamcrest-core-1.3.jar", "jetified-junit-1.1.2-api.jar");
499+
500+
// Verify :javalib module properties (plain Java library, not Android)
501+
assertThat(comparableProps)
502+
.doesNotContainKey(":javalib.sonar.android.detected")
503+
.containsEntry(":javalib.sonar.java.source", "1.8")
504+
.containsEntry(":javalib.sonar.java.target", "1.8")
505+
.containsEntry(":javalib.sonar.moduleKey", "org.sonarqube:example-android-gradle-dynamic-module:javalib")
506+
.containsEntry(":javalib.sonar.projectName", "javalib");
507+
508+
// Verify javalib does NOT contain Android-specific libraries
509+
assertThat(comparableProps.get(":javalib.sonar.java.libraries"))
510+
.doesNotContain("android.jar");
511+
assertThat(comparableProps.get(":javalib.sonar.java.test.libraries"))
512+
.isNotEmpty()
513+
.contains("junit-4.13.2.jar", "hamcrest-core-1.3.jar")
514+
.doesNotContain("android.jar", "jetified-junit-", "jetified-hamcrest-core-");
451515
}
452516
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
plugins {
2+
id 'com.android.application'
3+
}
4+
5+
android {
6+
compileSdkVersion 33
7+
8+
defaultConfig {
9+
applicationId "com.example.myapplication"
10+
minSdkVersion 21
11+
targetSdkVersion 33
12+
versionCode 1
13+
versionName "1.0"
14+
15+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
16+
}
17+
18+
buildTypes {
19+
release {
20+
minifyEnabled false
21+
}
22+
}
23+
dynamicFeatures = [':mydynamicfeature']
24+
namespace = "com.example.myapplication"
25+
}
26+
27+
dependencies {
28+
29+
implementation 'androidx.appcompat:appcompat:1.3.0'
30+
implementation 'com.google.android.material:material:1.3.0'
31+
testImplementation 'junit:junit:4.+'
32+
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
33+
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.example.myapplication;
2+
3+
import android.content.Context;
4+
import androidx.test.platform.app.InstrumentationRegistry;
5+
import androidx.test.ext.junit.runners.AndroidJUnit4;
6+
7+
import org.junit.Test;
8+
import org.junit.runner.RunWith;
9+
10+
import static org.junit.Assert.*;
11+
12+
/**
13+
* Instrumented test, which will execute on an Android device.
14+
*
15+
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
16+
*/
17+
@RunWith(AndroidJUnit4.class)
18+
public class ExampleInstrumentedTest {
19+
@Test
20+
public void useAppContext() {
21+
// Context of the app under test.
22+
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
23+
assertEquals("com.example.myapplication", appContext.getPackageName());
24+
}
25+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
package="com.example.myapplication">
4+
5+
<application
6+
android:allowBackup="true"
7+
android:label="@string/app_name"
8+
android:icon="@mipmap/ic_launcher"
9+
android:roundIcon="@mipmap/ic_launcher_round"
10+
android:supportsRtl="true"
11+
android:theme="@style/Theme.MyApplication"
12+
android:exported="true"/>
13+
</manifest>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package com.example.myapplication;
2+
3+
class MyApp {
4+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
xmlns:aapt="http://schemas.android.com/aapt"
3+
android:width="108dp"
4+
android:height="108dp"
5+
android:viewportWidth="108"
6+
android:viewportHeight="108">
7+
<path
8+
android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
9+
<aapt:attr name="android:fillColor">
10+
<gradient
11+
android:startY="49.59793"
12+
android:startX="42.9492"
13+
android:endY="92.4963"
14+
android:endX="85.84757"
15+
android:type="linear">
16+
<item
17+
android:color="#44000000"
18+
android:offset="0.0"/>
19+
<item
20+
android:color="#00000000"
21+
android:offset="1.0"/>
22+
</gradient>
23+
</aapt:attr>
24+
</path>
25+
<path
26+
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
27+
android:fillColor="#FFFFFF"
28+
android:fillType="nonZero"
29+
android:strokeWidth="1"
30+
android:strokeColor="#00000000"/>
31+
</vector>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<vector
3+
xmlns:android="http://schemas.android.com/apk/res/android"
4+
android:height="108dp"
5+
android:width="108dp"
6+
android:viewportHeight="108"
7+
android:viewportWidth="108">
8+
<path android:fillColor="#3DDC84"
9+
android:pathData="M0,0h108v108h-108z"/>
10+
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
11+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
12+
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
13+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
14+
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
15+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
16+
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
17+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
18+
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
19+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
20+
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
21+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
22+
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
23+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
24+
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
25+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
26+
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
27+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
28+
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
29+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
30+
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
31+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
32+
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
33+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
34+
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
35+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
36+
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
37+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
38+
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
39+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
40+
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
41+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
42+
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
43+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
44+
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
45+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
46+
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
47+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
48+
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
49+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
50+
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
51+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
52+
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
53+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
54+
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
55+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
56+
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
57+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
58+
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
59+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
60+
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
61+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
62+
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
63+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
64+
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
65+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
66+
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
67+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
68+
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
69+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
70+
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
71+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
72+
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
73+
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
74+
</vector>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
3+
<background android:drawable="@drawable/ic_launcher_background"/>
4+
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
5+
</adaptive-icon>

0 commit comments

Comments
 (0)