Enforce minSdk constraint for Android Flutter (#164251)
This commit adds validation for the Android SDK version within the existing dependency version checker. It introduces a warning when the SDK version is below a predefined threshold. The validation checks for the `minSdk` property in the `android` block of the app's `build.gradle` file. It will warn users if their `minSdk` version is out of Flutter's supported range and guide them on how to fix it. Fixes https://github.com/flutter/flutter/issues/134570 <!-- Thanks for filing a pull request! Reviewers are typically assigned within a week of filing a request. To learn more about code review, see our documentation on Tree Hygiene: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md --> ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
parent
0357b45337
commit
b771b39813
@ -3,12 +3,15 @@ package com.flutter.gradle
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import com.android.build.api.AndroidPluginVersion
|
||||
import com.android.build.api.variant.AndroidComponentsExtension
|
||||
import com.android.build.api.variant.Variant
|
||||
import org.gradle.api.JavaVersion
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.gradle.kotlin.dsl.extra
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper
|
||||
|
||||
object DependencyVersionChecker {
|
||||
// Logging constants.
|
||||
@VisibleForTesting internal const val GRADLE_NAME: String = "Gradle"
|
||||
|
||||
@VisibleForTesting internal const val JAVA_NAME: String = "Java"
|
||||
@ -17,11 +20,20 @@ object DependencyVersionChecker {
|
||||
|
||||
@VisibleForTesting internal const val KGP_NAME: String = "Kotlin"
|
||||
|
||||
@VisibleForTesting internal const val MIN_SDK_NAME: String = "minimum Android SDK"
|
||||
|
||||
// String constant that defines the name of the Gradle extra property that we set when
|
||||
// detecting that the project is using versions outside of Flutter's support range.
|
||||
// https://docs.gradle.org/current/kotlin-dsl/gradle/org.gradle.api/-project/index.html#-2107180640%2FProperties%2F-1867656071.
|
||||
@VisibleForTesting internal const val OUT_OF_SUPPORT_RANGE_PROPERTY = "usesUnsupportedDependencyVersions"
|
||||
|
||||
// The task prefix for assemble builds.
|
||||
@VisibleForTesting
|
||||
internal const val ASSEMBLE_PREFIX = "assemble"
|
||||
|
||||
// The task postfix to use when checking the minimum SDK version for each flavor.
|
||||
internal const val MIN_SDK_CHECK_TASK_POSTFIX = "MinSdkCheck"
|
||||
|
||||
// The following messages represent best effort guesses at where a Flutter developer should
|
||||
// look to upgrade a dependency that is below the corresponding threshold. Developers can
|
||||
// change some of these locations, so they are not guaranteed to be accurate.
|
||||
@ -58,6 +70,11 @@ object DependencyVersionChecker {
|
||||
"likely defined in the top-level build.gradle file " +
|
||||
"($projectDirectory/build.gradle) by the ext.kotlin_version property.\n"
|
||||
|
||||
@VisibleForTesting internal fun getPotentialSDKFix(projectDirectory: String): String =
|
||||
"Your project's minimum Android SDK version is typically " +
|
||||
"defined in the android block of the app-level `build.gradle(.kts)` file " +
|
||||
"($projectDirectory/app/build.gradle(.kts))."
|
||||
|
||||
// The following versions define our support policy for Gradle, Java, AGP, and KGP.
|
||||
// Before updating any "error" version, ensure that you have updated the corresponding
|
||||
// "warn" version for a full release to provide advanced warning. See
|
||||
@ -78,6 +95,13 @@ object DependencyVersionChecker {
|
||||
|
||||
@VisibleForTesting internal val errorKGPVersion: Version = Version(1, 7, 0)
|
||||
|
||||
// If this value is changed, then make sure to change the documentation on https://docs.flutter.dev/reference/supported-platforms
|
||||
@VisibleForTesting
|
||||
internal val warnMinSdkVersion: Int = 21
|
||||
|
||||
@VisibleForTesting
|
||||
internal val errorMinSdkVersion: Int = 1
|
||||
|
||||
/**
|
||||
* Checks if the project's Android build time dependencies are each within the respective
|
||||
* version range that we support. When we can't find a version for a given dependency
|
||||
@ -88,6 +112,9 @@ object DependencyVersionChecker {
|
||||
|
||||
checkGradleVersion(getGradleVersion(project), project)
|
||||
checkJavaVersion(getJavaVersion(), project)
|
||||
|
||||
configureMinSdkCheck(project)
|
||||
|
||||
val agpVersion: AndroidPluginVersion? = getAGPVersion(project)
|
||||
if (agpVersion != null) {
|
||||
checkAGPVersion(agpVersion, project)
|
||||
@ -105,6 +132,54 @@ object DependencyVersionChecker {
|
||||
// KGP is not required, so don't log any warning if we can't find the version.
|
||||
}
|
||||
|
||||
private fun configureMinSdkCheck(project: Project) {
|
||||
val androidComponents =
|
||||
project.extensions.findByType(AndroidComponentsExtension::class.java)
|
||||
|
||||
androidComponents?.onVariants(
|
||||
androidComponents.selector().all()
|
||||
) {
|
||||
val taskName = generateMinSdkCheckTaskName(it)
|
||||
val minSdkCheckTask =
|
||||
project.tasks.register(taskName) {
|
||||
doLast {
|
||||
val minSdkVersion = getMinSdkVersion(project, it)
|
||||
try {
|
||||
checkMinSdkVersion(minSdkVersion, project.rootDir.path, project.logger)
|
||||
} catch (e: DependencyValidationException) {
|
||||
project.extra.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
project.afterEvaluate {
|
||||
// Make assemble task depend on minSdkCheckTask for this variant.
|
||||
project.tasks
|
||||
.named(generateAssembleTaskName(it))
|
||||
.configure {
|
||||
dependsOn(minSdkCheckTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateAssembleTaskName(it: Variant) = "$ASSEMBLE_PREFIX${it.name.capitalize()}"
|
||||
|
||||
private fun generateMinSdkCheckTaskName(it: Variant) = "${it.name.capitalize()}$MIN_SDK_CHECK_TASK_POSTFIX"
|
||||
|
||||
private fun getMinSdkVersion(
|
||||
project: Project,
|
||||
it: Variant
|
||||
): MinSdkVersion {
|
||||
val agpVersion: AndroidPluginVersion? = getAGPVersion(project)
|
||||
return if (agpVersion != null && agpVersion.major >= 8 && agpVersion.minor >= 1) {
|
||||
MinSdkVersion(it.name, it.minSdk.apiLevel)
|
||||
} else {
|
||||
MinSdkVersion(it.name, it.minSdkVersion.apiLevel)
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.gradle.org/current/kotlin-dsl/gradle/org.gradle.api.invocation/-gradle/index.html#-837060600%2FFunctions%2F-1793262594
|
||||
@VisibleForTesting internal fun getGradleVersion(project: Project): Version {
|
||||
val untrimmedGradleVersion: String = project.gradle.gradleVersion
|
||||
@ -177,6 +252,12 @@ object DependencyVersionChecker {
|
||||
"\nAlternatively, use the flag \"--android-skip-build-dependency-validation\"" +
|
||||
" to bypass this check.\n\nPotential fix: $potentialFix"
|
||||
|
||||
@VisibleForTesting
|
||||
internal fun getFlavorSpecificMessage(
|
||||
flavorName: String?,
|
||||
dependencyName: String
|
||||
): String = dependencyName + (if (flavorName != null) " (flavor='$flavorName')" else "")
|
||||
|
||||
@VisibleForTesting internal fun checkGradleVersion(
|
||||
version: Version,
|
||||
project: Project
|
||||
@ -280,6 +361,33 @@ object DependencyVersionChecker {
|
||||
project.logger.error(warnMessage)
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting internal fun checkMinSdkVersion(
|
||||
minSdkVersion: MinSdkVersion,
|
||||
projectDirectory: String,
|
||||
logger: Logger
|
||||
) {
|
||||
// For Android SDK, only the major version is relevant, no need to do a full version check.
|
||||
if (minSdkVersion.version < errorMinSdkVersion) {
|
||||
val errorMessage: String =
|
||||
getErrorMessage(
|
||||
getFlavorSpecificMessage(minSdkVersion.flavor, MIN_SDK_NAME),
|
||||
minSdkVersion.version.toString(),
|
||||
errorMinSdkVersion.toString(),
|
||||
getPotentialSDKFix(projectDirectory)
|
||||
)
|
||||
throw DependencyValidationException(errorMessage)
|
||||
} else if (minSdkVersion.version < warnMinSdkVersion) {
|
||||
val warnMessage: String =
|
||||
getWarnMessage(
|
||||
getFlavorSpecificMessage(minSdkVersion.flavor, MIN_SDK_NAME),
|
||||
minSdkVersion.version.toString(),
|
||||
warnMinSdkVersion.toString(),
|
||||
getPotentialSDKFix(projectDirectory)
|
||||
)
|
||||
logger.error(warnMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper class to parse the versions that are provided as plain strings (Gradle, Kotlin) and
|
||||
@ -325,3 +433,14 @@ internal class Version(
|
||||
message: String? = null,
|
||||
cause: Throwable? = null
|
||||
) : Exception(message, cause)
|
||||
|
||||
/**
|
||||
* Represents the minimum Android SDK version for a specific product flavor.
|
||||
*
|
||||
* @param flavor The product flavor name, or null for the default configuration.
|
||||
* @param version The minimum Android SDK version (API level).
|
||||
*/
|
||||
@VisibleForTesting internal class MinSdkVersion(
|
||||
val flavor: String,
|
||||
val version: Int
|
||||
)
|
||||
|
@ -2,44 +2,56 @@ package com.flutter.gradle
|
||||
|
||||
import com.android.build.api.AndroidPluginVersion
|
||||
import com.android.build.api.variant.AndroidComponentsExtension
|
||||
import com.android.build.api.variant.Variant
|
||||
import com.flutter.gradle.DependencyVersionChecker.AGP_NAME
|
||||
import com.flutter.gradle.DependencyVersionChecker.GRADLE_NAME
|
||||
import com.flutter.gradle.DependencyVersionChecker.JAVA_NAME
|
||||
import com.flutter.gradle.DependencyVersionChecker.KGP_NAME
|
||||
import com.flutter.gradle.DependencyVersionChecker.MIN_SDK_NAME
|
||||
import com.flutter.gradle.DependencyVersionChecker.OUT_OF_SUPPORT_RANGE_PROPERTY
|
||||
import com.flutter.gradle.DependencyVersionChecker.POTENTIAL_JAVA_FIX
|
||||
import com.flutter.gradle.DependencyVersionChecker.errorAGPVersion
|
||||
import com.flutter.gradle.DependencyVersionChecker.errorGradleVersion
|
||||
import com.flutter.gradle.DependencyVersionChecker.errorKGPVersion
|
||||
import com.flutter.gradle.DependencyVersionChecker.errorMinSdkVersion
|
||||
import com.flutter.gradle.DependencyVersionChecker.getErrorMessage
|
||||
import com.flutter.gradle.DependencyVersionChecker.getFlavorSpecificMessage
|
||||
import com.flutter.gradle.DependencyVersionChecker.getPotentialAGPFix
|
||||
import com.flutter.gradle.DependencyVersionChecker.getPotentialGradleFix
|
||||
import com.flutter.gradle.DependencyVersionChecker.getPotentialKGPFix
|
||||
import com.flutter.gradle.DependencyVersionChecker.getPotentialSDKFix
|
||||
import com.flutter.gradle.DependencyVersionChecker.getWarnMessage
|
||||
import com.flutter.gradle.DependencyVersionChecker.warnAGPVersion
|
||||
import com.flutter.gradle.DependencyVersionChecker.warnGradleVersion
|
||||
import com.flutter.gradle.DependencyVersionChecker.warnJavaVersion
|
||||
import com.flutter.gradle.DependencyVersionChecker.warnKGPVersion
|
||||
import com.flutter.gradle.DependencyVersionChecker.warnMinSdkVersion
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.slot
|
||||
import io.mockk.verify
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.JavaVersion
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.gradle.api.plugins.ExtraPropertiesExtension
|
||||
import org.gradle.api.tasks.TaskContainer
|
||||
import org.gradle.internal.extensions.core.extra
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
const val FAKE_PROJECT_ROOT_DIR = "/fake/root/dir"
|
||||
private const val FAKE_PROJECT_ROOT_DIR = "/fake/root/dir"
|
||||
|
||||
// The following values will need to be modified when the corresponding "warn$DepName" versions
|
||||
// are updated in DependencyVersionChecker.kt
|
||||
const val SUPPORTED_GRADLE_VERSION: String = "7.4.2"
|
||||
val SUPPORTED_JAVA_VERSION: JavaVersion = JavaVersion.VERSION_11
|
||||
val SUPPORTED_AGP_VERSION: AndroidPluginVersion = AndroidPluginVersion(7, 3, 1)
|
||||
const val SUPPORTED_KGP_VERSION: String = "1.8.10"
|
||||
private const val SUPPORTED_GRADLE_VERSION: String = "7.4.2"
|
||||
private val SUPPORTED_JAVA_VERSION: JavaVersion = JavaVersion.VERSION_11
|
||||
private val SUPPORTED_AGP_VERSION: AndroidPluginVersion = AndroidPluginVersion(7, 3, 1)
|
||||
private const val SUPPORTED_KGP_VERSION: String = "1.8.10"
|
||||
private val SUPPORTED_SDK_VERSION: MinSdkVersion = MinSdkVersion("release", 30)
|
||||
|
||||
class DependencyVersionCheckerTest {
|
||||
@Test
|
||||
@ -209,6 +221,168 @@ class DependencyVersionCheckerTest {
|
||||
}
|
||||
verify(exactly = 0) { mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `min SDK version in warn range results in warning logs`() {
|
||||
val exampleWarnSDKVersion = 19
|
||||
val flavorName1 = "flavor1"
|
||||
val flavorName2 = "flavor2"
|
||||
val mockProject =
|
||||
MockProjectFactory.createMockProjectWithSpecifiedDependencyVersions(
|
||||
minSdkVersions =
|
||||
listOf(
|
||||
MinSdkVersion(flavorName1, exampleWarnSDKVersion),
|
||||
MinSdkVersion(flavorName2, exampleWarnSDKVersion)
|
||||
)
|
||||
)
|
||||
|
||||
val mockExtraPropertiesExtension = mockProject.extra
|
||||
every {
|
||||
mockExtraPropertiesExtension.set(
|
||||
OUT_OF_SUPPORT_RANGE_PROPERTY,
|
||||
false
|
||||
)
|
||||
} returns Unit
|
||||
val mockLogger = mockProject.logger
|
||||
every { mockLogger.error(any()) } returns Unit
|
||||
|
||||
DependencyVersionChecker.checkDependencyVersions(mockProject)
|
||||
verify {
|
||||
mockLogger.error(
|
||||
getWarnMessage(
|
||||
getFlavorSpecificMessage(flavorName1, MIN_SDK_NAME),
|
||||
exampleWarnSDKVersion.toString(),
|
||||
warnMinSdkVersion.toString(),
|
||||
getPotentialSDKFix(FAKE_PROJECT_ROOT_DIR)
|
||||
)
|
||||
)
|
||||
mockLogger.error(
|
||||
getWarnMessage(
|
||||
getFlavorSpecificMessage(flavorName2, MIN_SDK_NAME),
|
||||
exampleWarnSDKVersion.toString(),
|
||||
warnMinSdkVersion.toString(),
|
||||
getPotentialSDKFix(FAKE_PROJECT_ROOT_DIR)
|
||||
)
|
||||
)
|
||||
}
|
||||
verify(exactly = 0) {
|
||||
mockExtraPropertiesExtension.set(
|
||||
OUT_OF_SUPPORT_RANGE_PROPERTY,
|
||||
true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `min SDK version in error range results in DependencyValidationException`() {
|
||||
val exampleErrorSDKVersion = 0
|
||||
val flavorName = "flavor1"
|
||||
val mockProject =
|
||||
MockProjectFactory.createMockProjectWithSpecifiedDependencyVersions(
|
||||
minSdkVersions =
|
||||
listOf(
|
||||
MinSdkVersion(flavorName, exampleErrorSDKVersion)
|
||||
)
|
||||
)
|
||||
|
||||
val mockExtraPropertiesExtension = mockProject.extra
|
||||
val mockLogger = mockProject.logger
|
||||
every { mockExtraPropertiesExtension.set(any(), any()) } returns Unit
|
||||
every { mockLogger.error(any()) } returns Unit
|
||||
|
||||
val dependencyValidationException =
|
||||
assertFailsWith<DependencyValidationException> {
|
||||
DependencyVersionChecker.checkDependencyVersions(
|
||||
mockProject
|
||||
)
|
||||
}
|
||||
|
||||
assert(
|
||||
dependencyValidationException.message ==
|
||||
getErrorMessage(
|
||||
getFlavorSpecificMessage(flavorName, MIN_SDK_NAME),
|
||||
exampleErrorSDKVersion.toString(),
|
||||
errorMinSdkVersion.toString(),
|
||||
getPotentialSDKFix(FAKE_PROJECT_ROOT_DIR)
|
||||
)
|
||||
)
|
||||
verify(exactly = 1) {
|
||||
mockExtraPropertiesExtension.set(
|
||||
OUT_OF_SUPPORT_RANGE_PROPERTY,
|
||||
true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `checkMinSdkVersion throws error when in error range for min SDK version`() {
|
||||
val mockLogger = mockk<Logger>()
|
||||
val mockExtraPropertiesExtension = mockk<ExtraPropertiesExtension>()
|
||||
val projectDir = "projectDir"
|
||||
val flavor = "flavor"
|
||||
val version = 0
|
||||
|
||||
every { mockExtraPropertiesExtension.set(any(), any()) } returns Unit
|
||||
every { mockLogger.error(any()) } returns Unit
|
||||
|
||||
val dependencyValidationException =
|
||||
assertFailsWith<DependencyValidationException> {
|
||||
DependencyVersionChecker.checkMinSdkVersion(
|
||||
minSdkVersion = MinSdkVersion(flavor, version),
|
||||
projectDirectory = projectDir,
|
||||
logger = mockLogger
|
||||
)
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
dependencyValidationException.message,
|
||||
"Error: Your project's minimum Android SDK (flavor='flavor') version (0) is lower than " +
|
||||
"Flutter's minimum supported version of 1. Please upgrade your minimum Android SDK " +
|
||||
"(flavor='flavor') version. \n" +
|
||||
"Alternatively, use the flag \"--android-skip-build-dependency-validation\" to " +
|
||||
"bypass this check.\n" +
|
||||
"\n" +
|
||||
"Potential fix: Your project's minimum Android SDK version is typically defined in " +
|
||||
"the android block of the app-level `build.gradle(.kts)` file " +
|
||||
"(projectDir/app/build.gradle(.kts))."
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `checkMinSdkVersion logs warning when in warning range for min SDK version`() {
|
||||
val mockLogger = mockk<Logger>()
|
||||
val mockExtraPropertiesExtension = mockk<ExtraPropertiesExtension>()
|
||||
val projectDir = "projectDir"
|
||||
val flavor = "flavor"
|
||||
val version = 20
|
||||
|
||||
every { mockExtraPropertiesExtension.set(any(), any()) } returns Unit
|
||||
every { mockLogger.error(any()) } returns Unit
|
||||
|
||||
DependencyVersionChecker.checkMinSdkVersion(
|
||||
minSdkVersion = MinSdkVersion(flavor, version),
|
||||
projectDirectory = projectDir,
|
||||
logger = mockLogger
|
||||
)
|
||||
|
||||
val warningMessageSlot = slot<String>()
|
||||
verify {
|
||||
mockLogger.error(capture(warningMessageSlot))
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
warningMessageSlot.captured,
|
||||
"Warning: Flutter support for your project's minimum Android SDK (flavor='flavor') " +
|
||||
"version (20) will soon be dropped. Please upgrade your minimum Android SDK " +
|
||||
"(flavor='flavor') version to a version of at least 21 soon.\n" +
|
||||
"Alternatively, use the flag \"--android-skip-build-dependency-validation\" to " +
|
||||
"bypass this check.\n" +
|
||||
"\n" +
|
||||
"Potential fix: Your project's minimum Android SDK version is typically defined in " +
|
||||
"the android block of the app-level `build.gradle(.kts)` file " +
|
||||
"(projectDir/app/build.gradle(.kts))."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// There isn't a way to create a real org.gradle.api.Project object for testing unfortunately, so
|
||||
@ -219,12 +393,13 @@ class DependencyVersionCheckerTest {
|
||||
// https://github.com/autonomousapps/dependency-analysis-gradle-plugin/tree/main/testkit
|
||||
// as a way to fill this gap in testing (combined with moving functionality to individual tasks
|
||||
// that can be tested independently).
|
||||
object MockProjectFactory {
|
||||
private object MockProjectFactory {
|
||||
fun createMockProjectWithSpecifiedDependencyVersions(
|
||||
javaVersion: JavaVersion = SUPPORTED_JAVA_VERSION,
|
||||
gradleVersion: String = SUPPORTED_GRADLE_VERSION,
|
||||
agpVersion: AndroidPluginVersion = SUPPORTED_AGP_VERSION,
|
||||
kgpVersion: String = SUPPORTED_KGP_VERSION
|
||||
kgpVersion: String = SUPPORTED_KGP_VERSION,
|
||||
minSdkVersions: List<MinSdkVersion> = listOf(SUPPORTED_SDK_VERSION)
|
||||
): Project {
|
||||
// Java
|
||||
mockkStatic(JavaVersion::class)
|
||||
@ -254,6 +429,54 @@ object MockProjectFactory {
|
||||
// Project path
|
||||
every { mockProject.rootDir.path } returns FAKE_PROJECT_ROOT_DIR
|
||||
|
||||
// SDK
|
||||
val actionSlot = slot<Action<Project>>()
|
||||
every { mockProject.afterEvaluate(capture(actionSlot)) } answers {
|
||||
actionSlot.captured.execute(mockProject)
|
||||
return@answers Unit
|
||||
}
|
||||
val onVariantsFnSlot = slot<(Variant) -> Unit>()
|
||||
every { mockAndroidComponentsExtension.selector() } returns
|
||||
mockk {
|
||||
every { all() } returns mockk()
|
||||
}
|
||||
every { mockProject.tasks } returns
|
||||
mockk<TaskContainer> {
|
||||
val registerTaskSlot = slot<Action<Task>>()
|
||||
every { register(any(), capture(registerTaskSlot)) } answers registerAnswer@{
|
||||
registerTaskSlot.captured.execute(
|
||||
mockk {
|
||||
val doLastActionSlot = slot<Action<Task>>()
|
||||
every { doLast(capture(doLastActionSlot)) } answers doLastAnswer@{
|
||||
doLastActionSlot.captured.execute(mockk())
|
||||
return@doLastAnswer mockk()
|
||||
}
|
||||
}
|
||||
)
|
||||
return@registerAnswer mockk()
|
||||
}
|
||||
|
||||
every { named(any<String>()) } returns
|
||||
mockk {
|
||||
every { configure(any<Action<Task>>()) } returns mockk()
|
||||
}
|
||||
}
|
||||
every {
|
||||
mockAndroidComponentsExtension.onVariants(
|
||||
any(),
|
||||
capture(onVariantsFnSlot)
|
||||
)
|
||||
} answers {
|
||||
minSdkVersions.forEach {
|
||||
val variant = mockk<Variant>()
|
||||
every { variant.name } returns it.flavor
|
||||
every { variant.minSdk } returns mockk { every { apiLevel } returns it.version }
|
||||
every { variant.minSdkVersion } returns mockk { every { apiLevel } returns it.version }
|
||||
onVariantsFnSlot.captured.invoke(variant)
|
||||
}
|
||||
return@answers Unit
|
||||
}
|
||||
|
||||
return mockProject
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user