Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package io.sentry.android.gradle.integration

import io.sentry.BuildConfig
import io.sentry.android.gradle.util.AgpVersions
import io.sentry.android.gradle.util.GradleVersions
import io.sentry.android.gradle.util.SemVer
import java.io.File
import kotlin.test.assertFalse
import kotlin.test.assertTrue
import org.gradle.testkit.runner.internal.PluginUnderTestMetadataReading
import org.gradle.util.GradleVersion
import org.hamcrest.CoreMatchers.`is`
import org.junit.Assume.assumeThat
import org.junit.Test

class SentryPluginIsolatedProjectsTest :
BaseSentryPluginTest(BuildConfig.AgpVersion, GradleVersion.current().version) {

@Test
fun `plugin is compatible with isolated projects in a multi-module build`() {
assumeThat(
"Isolated Projects requires AGP 8.3.0+ and Gradle 8.0+",
SemVer.parse(BuildConfig.AgpVersion) >= AgpVersions.VERSION_8_3_0 &&
GradleVersions.CURRENT >= GradleVersions.VERSION_8_0,
`is`(true),
)

writeIsolatedProjectsFixture()

runner.appendArguments(":app:assembleDebug").appendArguments("--configuration-cache")

val output = runner.build().output

assertTrue(output) { "BUILD SUCCESSFUL" in output }
// Sanity-check that isolated-projects was actually active during this build —
// otherwise the test would silently degrade into a plain config-cache test.
assertTrue(output) { "isolated projects" in output.lowercase() }
assertFalse(
"problems were found " in output || "cannot access '" in output,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assertion misses singular "problem was found" Gradle output

Low Severity

The violation check "problems were found " only matches the plural Gradle output (2+ problems) but not the singular "1 problem was found" form that Gradle uses for exactly one violation. If a single isolated-projects violation occurs whose message doesn't contain "cannot access '", the assertFalse passes silently, defeating the purpose of this guard. Matching on "problem" (without the 's') or both forms would close this gap.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3e37caa. Configure here.

"Expected no isolated-projects violations, but got:\n$output",
)
}

private fun writeIsolatedProjectsFixture() {
// Replace the fixture written by BaseSentryPluginTest — its root build.gradle
// uses allprojects {} and subprojects {}, which are fundamentally incompatible
// with Gradle's isolated-projects feature. Instead, wire everything per-project
// and add an Android library module that :app depends on, so we exercise
// cross-project configuration (the interesting scenario for Isolated Projects).
//
// autoInstallation is intentionally left disabled: it walks the dependency
// graph at configuration time and reaches into sibling projects' metadata
// (Project.group), which violates Isolated Projects. Tracked in EME-1072.
val pluginClasspath =
PluginUnderTestMetadataReading.readImplementationClasspath()
.joinToString(separator = ", ") { "\"$it\"" }
.replace(File.separator, "/")

File(testProjectDir.root, "settings.gradle")
.writeText(
// language=Groovy
"""
include ':app', ':library'
"""
.trimIndent()
)

File(testProjectDir.root, "gradle.properties")
.writeText(
"""
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8
org.gradle.daemon=false
org.gradle.unsafe.isolated-projects=true
android.useAndroidX=true
android.overrideVersionCheck=true
"""
.trimIndent()
)

File(testProjectDir.root, "build.gradle")
.writeText(
// language=Groovy
"""
buildscript {
repositories {
google()
gradlePluginPortal()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:$androidGradlePluginVersion'
classpath files($pluginClasspath)
}
}
"""
.trimIndent()
)

File(testProjectDir.root, "app/build.gradle")
.writeText(
// language=Groovy
"""
plugins {
id 'com.android.application'
id 'io.sentry.android.gradle'
}

repositories {
google()
mavenCentral()
}

android {
namespace 'com.example'
compileSdkVersion 35
defaultConfig {
applicationId 'com.example'
minSdkVersion 21
}
}

dependencies {
implementation project(':library')
}

sentry {
autoUploadProguardMapping = true
autoInstallation.enabled = false
telemetry = true
}
"""
.trimIndent()
)

val libraryDir = File(testProjectDir.root, "library").apply { mkdirs() }
File(libraryDir, "build.gradle")
.writeText(
// language=Groovy
"""
plugins {
id 'com.android.library'
id 'io.sentry.android.gradle'
}

repositories {
google()
mavenCentral()
}

android {
namespace 'com.example.library'
compileSdkVersion 35
defaultConfig {
minSdkVersion 21
}
}

sentry {
autoUploadProguardMapping = false
autoInstallation.enabled = false
telemetry = false
}
"""
.trimIndent()
)
}
}
Loading