mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
fix(tooling-api): fetch variant-specific application IDs in application projects (#1387)
This commit is contained in:
Generated
-3
@@ -134,9 +134,6 @@
|
||||
<module name="AndroidIDE.templates-testing.test" target="11" />
|
||||
<module name="AndroidIDE.testing-android" target="17" />
|
||||
<module name="AndroidIDE.testing.android.test" target="11" />
|
||||
<module name="AndroidIDE.testing.common" target="11" />
|
||||
<module name="AndroidIDE.testing.common.main" target="11" />
|
||||
<module name="AndroidIDE.testing.common.test" target="11" />
|
||||
<module name="AndroidIDE.testing.tooling-api" target="11" />
|
||||
<module name="AndroidIDE.testing.tooling-api.main" target="11" />
|
||||
<module name="AndroidIDE.testing.tooling-api.test" target="11" />
|
||||
|
||||
@@ -28,6 +28,7 @@ plugins {
|
||||
alias(libs.plugins.android.application) apply false
|
||||
alias(libs.plugins.android.library) apply false
|
||||
alias(libs.plugins.kotlin.android) apply false
|
||||
alias(libs.plugins.kotlin.jvm) apply false
|
||||
alias(libs.plugins.maven.publish) apply false
|
||||
alias(libs.plugins.gradle.publish) apply false
|
||||
}
|
||||
|
||||
@@ -148,5 +148,6 @@ maven-publish = { module = "com.vanniktech:gradle-maven-publish-plugin", version
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
android-library = { id = "com.android.library", version.ref = "agp" }
|
||||
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||
maven-publish = { id = "com.vanniktech.maven.publish.base", version.ref = "maven-publish-plugin" }
|
||||
gradle-publish = { id = "com.gradle.plugin-publish", version = "1.2.1" }
|
||||
|
||||
@@ -112,6 +112,7 @@ include(
|
||||
":termux:termux-shared",
|
||||
":termux:termux-view",
|
||||
":testing:android",
|
||||
":testing:common",
|
||||
":testing:lsp",
|
||||
":testing:tooling",
|
||||
":testing:unit",
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.utils
|
||||
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* Capitalizes the string.
|
||||
*/
|
||||
@JvmOverloads
|
||||
fun String.capitalizeString(locale: Locale = Locale.getDefault()): String {
|
||||
return replaceFirstChar { char ->
|
||||
if (char.isLowerCase()) char.titlecase(locale) else char.toString()
|
||||
}
|
||||
}
|
||||
+1
-4
@@ -26,14 +26,11 @@ import com.itsaky.androidide.projects.IProjectManager
|
||||
import com.itsaky.androidide.projects.ProjectManagerImpl
|
||||
import com.itsaky.androidide.projects.builder.BuildService
|
||||
import com.itsaky.androidide.tooling.api.IAndroidProject
|
||||
import com.itsaky.androidide.tooling.api.messages.InitializeProjectParams
|
||||
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher
|
||||
import com.itsaky.androidide.testing.tooling.ToolingApiTestLauncher
|
||||
import com.itsaky.androidide.utils.FileProvider
|
||||
import com.itsaky.androidide.utils.SourceClassTrie.SourceNode
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
import kotlin.io.path.pathString
|
||||
import kotlin.io.path.writeText
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
+97
-36
@@ -17,10 +17,13 @@
|
||||
|
||||
package com.itsaky.androidide.tooling.impl.internal
|
||||
|
||||
import com.android.builder.model.v2.dsl.BuildType
|
||||
import com.android.builder.model.v2.ide.AndroidArtifact
|
||||
import com.android.builder.model.v2.ide.GraphItem
|
||||
import com.android.builder.model.v2.ide.Library
|
||||
import com.android.builder.model.v2.ide.ProjectType
|
||||
import com.android.builder.model.v2.ide.Variant
|
||||
import com.android.builder.model.v2.models.AndroidDsl
|
||||
import com.android.builder.model.v2.models.AndroidProject
|
||||
import com.android.builder.model.v2.models.BasicAndroidProject
|
||||
import com.android.builder.model.v2.models.VariantDependencies
|
||||
@@ -40,9 +43,9 @@ import com.itsaky.androidide.tooling.api.models.ProjectMetadata
|
||||
import com.itsaky.androidide.tooling.api.models.params.StringParameter
|
||||
import com.itsaky.androidide.tooling.api.util.AndroidModulePropertyCopier
|
||||
import com.itsaky.androidide.tooling.api.util.AndroidModulePropertyCopier.copy
|
||||
import com.itsaky.androidide.tooling.api.util.compareSemanticVersions
|
||||
import com.itsaky.androidide.tooling.api.util.extractPackageName
|
||||
import com.itsaky.androidide.utils.AndroidPluginVersion
|
||||
import com.itsaky.androidide.utils.capitalizeString
|
||||
import org.gradle.tooling.model.GradleProject
|
||||
import java.io.File
|
||||
import java.io.Serializable
|
||||
@@ -57,7 +60,8 @@ internal class AndroidProjectImpl(
|
||||
private val basicAndroidProject: BasicAndroidProject,
|
||||
private val androidProject: AndroidProject,
|
||||
private val variantDependencies: VariantDependencies,
|
||||
private val versions: Versions
|
||||
private val versions: Versions,
|
||||
private val androidDsl: AndroidDsl,
|
||||
) : GradleProjectImpl(gradleProject), IAndroidProject, Serializable {
|
||||
|
||||
private val serialVersionUID = 1L
|
||||
@@ -84,10 +88,9 @@ internal class AndroidProjectImpl(
|
||||
}
|
||||
}
|
||||
|
||||
private fun AndroidArtifact.toMetadata(name: String): AndroidArtifactMetadata {
|
||||
return AndroidArtifactMetadata(
|
||||
name = name,
|
||||
resGenTaskName = resGenTaskName,
|
||||
private fun AndroidArtifact.toMetadata(variantName: String): AndroidArtifactMetadata {
|
||||
return AndroidArtifactMetadata(name = variantName,
|
||||
applicationId = computeApplicationId(variantName), resGenTaskName = resGenTaskName,
|
||||
assembleTaskOutputListingFile = assembleTaskOutputListingFile,
|
||||
generatedResourceFolders = generatedResourceFolders,
|
||||
generatedSourceFolders = generatedSourceFolders, maxSdkVersion = maxSdkVersion,
|
||||
@@ -95,8 +98,7 @@ internal class AndroidProjectImpl(
|
||||
sourceGenTaskName = sourceGenTaskName, assembleTaskName = assembleTaskName,
|
||||
classJars = classesFolders.filter { it.name.endsWith(".jar") },
|
||||
compileTaskName = compileTaskName,
|
||||
targetSdkVersionOverride = targetSdkVersionOverride?.apiLevel ?: -1
|
||||
)
|
||||
targetSdkVersionOverride = targetSdkVersionOverride?.apiLevel ?: -1)
|
||||
}
|
||||
|
||||
override fun getVariant(param: StringParameter): CompletableFuture<AndroidVariantMetadata?> {
|
||||
@@ -106,11 +108,8 @@ internal class AndroidProjectImpl(
|
||||
}
|
||||
|
||||
private fun Variant.toMetadata(): AndroidVariantMetadata {
|
||||
return AndroidVariantMetadata(
|
||||
name = name,
|
||||
mainArtifact = mainArtifact.toMetadata(name),
|
||||
otherArtifacts = mutableMapOf()
|
||||
)
|
||||
return AndroidVariantMetadata(name = name, mainArtifact = mainArtifact.toMetadata(name),
|
||||
otherArtifacts = mutableMapOf())
|
||||
}
|
||||
|
||||
override fun getBootClasspaths(): CompletableFuture<Collection<File>> {
|
||||
@@ -131,11 +130,8 @@ internal class AndroidProjectImpl(
|
||||
}
|
||||
}
|
||||
|
||||
private fun fillLibrary(
|
||||
item: GraphItem,
|
||||
libraries: Map<String, Library>,
|
||||
seen: HashMap<String, DefaultLibrary>
|
||||
): DefaultLibrary? {
|
||||
private fun fillLibrary(item: GraphItem, libraries: Map<String, Library>,
|
||||
seen: HashMap<String, DefaultLibrary>): DefaultLibrary? {
|
||||
|
||||
val lib = libraries[item.key] ?: return null
|
||||
val library = copy(lib)
|
||||
@@ -164,8 +160,9 @@ internal class AndroidProjectImpl(
|
||||
return CompletableFuture.supplyAsync {
|
||||
|
||||
// model sync files available only in v7.3.0 and later
|
||||
return@supplyAsync if (AndroidPluginVersion.parse(versions.agp) >= AndroidPluginVersion(7, 3, 0))
|
||||
copy(androidProject.modelSyncFiles)
|
||||
return@supplyAsync if (AndroidPluginVersion.parse(versions.agp) >= AndroidPluginVersion(7, 3,
|
||||
0)
|
||||
) copy(androidProject.modelSyncFiles)
|
||||
else emptyList()
|
||||
}
|
||||
}
|
||||
@@ -191,22 +188,13 @@ internal class AndroidProjectImpl(
|
||||
val gradleMetadata = super.getMetadata().get()
|
||||
|
||||
val viewBindingOptions = androidProject.viewBindingOptions?.let(
|
||||
AndroidModulePropertyCopier::copy)
|
||||
?: DefaultViewBindingOptions()
|
||||
AndroidModulePropertyCopier::copy) ?: DefaultViewBindingOptions()
|
||||
|
||||
return@supplyAsync AndroidProjectMetadata(
|
||||
gradleMetadata,
|
||||
packageName,
|
||||
basicAndroidProject.projectType,
|
||||
copy(androidProject.flags),
|
||||
copy(androidProject.javaCompileOptions),
|
||||
viewBindingOptions,
|
||||
androidProject.resourcePrefix,
|
||||
androidProject.namespace,
|
||||
androidProject.androidTestNamespace,
|
||||
androidProject.testFixturesNamespace,
|
||||
getClassesJar()
|
||||
)
|
||||
return@supplyAsync AndroidProjectMetadata(gradleMetadata, packageName,
|
||||
basicAndroidProject.projectType, copy(androidProject.flags),
|
||||
copy(androidProject.javaCompileOptions), viewBindingOptions, androidProject.resourcePrefix,
|
||||
androidProject.namespace, androidProject.androidTestNamespace,
|
||||
androidProject.testFixturesNamespace, getClassesJar())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,4 +222,77 @@ internal class AndroidProjectImpl(
|
||||
this.packageName = extractPackageName(manifestFile) ?: UNKNOWN_PACKAGE
|
||||
this.shouldLookupPackage = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun AndroidArtifact.computeApplicationId(variantName: String): String? {
|
||||
val minAgpForAppId = AndroidPluginVersion(7, 4, 0)
|
||||
return if (minAgpForAppId <= AndroidPluginVersion.parse(versions.agp)) {
|
||||
applicationId
|
||||
} else {
|
||||
computeApplicationIdLegacy(variantName)
|
||||
}
|
||||
}
|
||||
|
||||
// Adapted from the following :
|
||||
// https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ComponentDslInfoImpl.kt;drc=6a5551bdea55c0c991f1ccf1e3f8f6f3d2cd2cb7;l=107
|
||||
// https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/VariantDslInfoImpl.kt;drc=d44f5b98cd5530eceb230e0d151ad96c4277f78d;l=109
|
||||
|
||||
protected fun computeApplicationIdLegacy(variantName: String): String {
|
||||
val basicVariant = basicAndroidProject.variants.firstOrNull { it.name == variantName }
|
||||
val buildType = basicVariant?.buildType?.let { buildTypeName ->
|
||||
androidDsl.buildTypes.find { buildType -> buildType.name == buildTypeName }
|
||||
}!!
|
||||
|
||||
val appIdFromFlavor = if (basicAndroidProject.projectType == ProjectType.APPLICATION) {
|
||||
androidDsl.productFlavors.find { flavor ->
|
||||
"${flavor.name}${buildType.name.capitalizeString()}" == variantName
|
||||
}?.applicationId
|
||||
} else {
|
||||
androidDsl.defaultConfig.applicationId
|
||||
}
|
||||
|
||||
return if (appIdFromFlavor == null) {
|
||||
// No appId value set from DSL; use the namespace value from the DSL.
|
||||
"${androidProject.namespace}${computeApplicationIdSuffix(variantName, buildType)}"
|
||||
} else {
|
||||
// use value from flavors/defaultConfig
|
||||
// needed to make nullability work in kotlinc
|
||||
val finalAppIdFromFlavors: String = appIdFromFlavor
|
||||
"$finalAppIdFromFlavors${computeApplicationIdSuffix(variantName, buildType)}"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines all the appId suffixes into a single one.
|
||||
*
|
||||
* The suffixes are separated by '.' whether their first char is a '.' or not.
|
||||
*/
|
||||
protected fun computeApplicationIdSuffix(variantName: String, buildType: BuildType): String {
|
||||
// for the suffix we combine the suffix from all the flavors. However, we're going to
|
||||
// want the higher priority one to be last.
|
||||
val suffixes = mutableListOf<String>()
|
||||
androidDsl.defaultConfig.applicationIdSuffix?.let {
|
||||
suffixes.add(it)
|
||||
}
|
||||
|
||||
if (basicAndroidProject.projectType == ProjectType.APPLICATION) {
|
||||
|
||||
val flavorSuffix = androidDsl.productFlavors.find { flavor ->
|
||||
"${flavor.name}${buildType.name.capitalizeString()}" == variantName
|
||||
}?.applicationIdSuffix
|
||||
|
||||
flavorSuffix?.also { suffixes.add(flavorSuffix) }
|
||||
|
||||
// then we add the build type after.
|
||||
buildType.applicationIdSuffix?.also {
|
||||
suffixes.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
val nonEmptySuffixes = suffixes.filter { it.isNotEmpty() }
|
||||
return if (nonEmptySuffixes.isNotEmpty()) {
|
||||
".${nonEmptySuffixes.joinToString(separator = ".", transform = { it.removePrefix(".") })}"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.itsaky.androidide.tooling.impl.sync
|
||||
|
||||
import com.android.builder.model.v2.models.AndroidDsl
|
||||
import com.android.builder.model.v2.models.AndroidProject
|
||||
import com.android.builder.model.v2.models.BasicAndroidProject
|
||||
import com.android.builder.model.v2.models.ModelBuilderParameter
|
||||
@@ -40,6 +41,7 @@ class AndroidProjectModelBuilder(initializationParams: InitializeProjectParams)
|
||||
val projectPath = module.gradleProject.path
|
||||
val basicModel = controller.getModelAndLog(module, BasicAndroidProject::class.java)
|
||||
val androidModel = controller.getModelAndLog(module, AndroidProject::class.java)
|
||||
val androidDsl = controller.getModelAndLog(module, AndroidDsl::class.java)
|
||||
|
||||
val variantNames = basicModel.variants.map { it.name }
|
||||
log(
|
||||
@@ -80,7 +82,8 @@ class AndroidProjectModelBuilder(initializationParams: InitializeProjectParams)
|
||||
basicModel,
|
||||
androidModel,
|
||||
variantDependencies,
|
||||
versions
|
||||
versions,
|
||||
androidDsl
|
||||
)
|
||||
}
|
||||
}
|
||||
+473
@@ -0,0 +1,473 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.tooling.impl
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.itsaky.androidide.testing.tooling.ToolingApiTestLauncher
|
||||
import com.itsaky.androidide.tooling.api.IAndroidProject
|
||||
import com.itsaky.androidide.tooling.api.models.params.StringParameter
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.JUnit4
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
@RunWith(JUnit4::class)
|
||||
class ApplicationIDComputationTest {
|
||||
|
||||
@Test
|
||||
fun `test variant-specific application ID computation for default applicationId`() {
|
||||
// no custom applicationIdSuffix or applicationId is set
|
||||
val (_, project, initializeResult) = ToolingApiTestLauncher().launchServer()
|
||||
|
||||
assertThat(initializeResult).isNotNull()
|
||||
assertThat(initializeResult?.isSuccessful).isTrue()
|
||||
assertThat(initializeResult?.failure).isNull()
|
||||
|
||||
assertThat(project).isNotNull()
|
||||
|
||||
val selectionResult = project.selectProject(StringParameter(":app")).get()
|
||||
assertThat(selectionResult).isNotNull()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val app = project.asAndroidProject()
|
||||
assertThat(app).isNotNull()
|
||||
assertThat(app).isInstanceOf(IAndroidProject::class.java)
|
||||
|
||||
val variants = app.getVariants().get()
|
||||
assertThat(variants).isNotNull()
|
||||
assertThat(variants).isNotEmpty()
|
||||
|
||||
|
||||
assertThat(variants).hasSize(2)
|
||||
assertThat(variants.map { it.name }).containsExactly("debug", "release")
|
||||
|
||||
variants.forEach { variant ->
|
||||
val applicationId = variant.mainArtifact.applicationId
|
||||
assertThat(applicationId).isNotNull()
|
||||
assertThat(applicationId?.trim()).isNotEmpty()
|
||||
assertThat(applicationId).isEqualTo("com.itsaky.test.app")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test variant-specific application ID computation for product flavors with applicationIdSuffix`() {
|
||||
// only the flavors have applicationIdSuffix set, not the build types
|
||||
val androidBlockConfig = """
|
||||
flavorDimensions.add("default")
|
||||
|
||||
productFlavors {
|
||||
create("full") {
|
||||
dimension = "default"
|
||||
applicationIdSuffix = ".full"
|
||||
}
|
||||
create("demo") {
|
||||
dimension = "default"
|
||||
applicationIdSuffix = ".demo"
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
val client = ToolingApiTestLauncher.MultiVersionTestClient(
|
||||
androidBlockConfig = androidBlockConfig)
|
||||
val (_, project, initializeResult) = ToolingApiTestLauncher().launchServer(client = client)
|
||||
|
||||
assertThat(initializeResult).isNotNull()
|
||||
assertThat(initializeResult?.isSuccessful).isTrue()
|
||||
assertThat(initializeResult?.failure).isNull()
|
||||
|
||||
assertThat(project).isNotNull()
|
||||
|
||||
val selectionResult = project.selectProject(StringParameter(":app")).get()
|
||||
assertThat(selectionResult).isNotNull()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val app = project.asAndroidProject()
|
||||
assertThat(app).isNotNull()
|
||||
assertThat(app).isInstanceOf(IAndroidProject::class.java)
|
||||
|
||||
val variants = app.getVariants().get()
|
||||
assertThat(variants).isNotNull()
|
||||
assertThat(variants).isNotEmpty()
|
||||
|
||||
|
||||
assertThat(variants).hasSize(4)
|
||||
assertThat(variants.map { it.name }).containsExactly("fullDebug", "fullRelease", "demoDebug",
|
||||
"demoRelease")
|
||||
|
||||
variants.forEach { variant ->
|
||||
val applicationId = variant.mainArtifact.applicationId
|
||||
assertThat(applicationId).isNotNull()
|
||||
assertThat(applicationId?.trim()).isNotEmpty()
|
||||
assertThat(applicationId).isAnyOf("com.itsaky.test.app.full", "com.itsaky.test.app.demo")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test variant-specific application ID computation for product flavors with applicationIdSuffix and multiple build types`() {
|
||||
// only the flavors have applicationIdSuffix set, but additional build types have been created
|
||||
val androidBlockConfig = """
|
||||
flavorDimensions.add("default")
|
||||
|
||||
productFlavors {
|
||||
create("full") {
|
||||
dimension = "default"
|
||||
applicationIdSuffix = ".full"
|
||||
}
|
||||
create("demo") {
|
||||
dimension = "default"
|
||||
applicationIdSuffix = ".demo"
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
create("staging") {}
|
||||
create("experimental") {}
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
val client = ToolingApiTestLauncher.MultiVersionTestClient(
|
||||
androidBlockConfig = androidBlockConfig)
|
||||
val (_, project, initializeResult) = ToolingApiTestLauncher().launchServer(client = client)
|
||||
|
||||
assertThat(initializeResult).isNotNull()
|
||||
assertThat(initializeResult?.isSuccessful).isTrue()
|
||||
assertThat(initializeResult?.failure).isNull()
|
||||
|
||||
assertThat(project).isNotNull()
|
||||
|
||||
val selectionResult = project.selectProject(StringParameter(":app")).get()
|
||||
assertThat(selectionResult).isNotNull()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val app = project.asAndroidProject()
|
||||
assertThat(app).isNotNull()
|
||||
assertThat(app).isInstanceOf(IAndroidProject::class.java)
|
||||
|
||||
val variants = app.getVariants().get()
|
||||
assertThat(variants).isNotNull()
|
||||
assertThat(variants).isNotEmpty()
|
||||
|
||||
|
||||
assertThat(variants).hasSize(8)
|
||||
assertThat(variants.map { it.name }).containsExactly("fullDebug", "fullRelease", "fullStaging",
|
||||
"fullExperimental", "demoDebug", "demoRelease", "demoStaging", "demoExperimental")
|
||||
|
||||
variants.forEach { variant ->
|
||||
val applicationId = variant.mainArtifact.applicationId
|
||||
assertThat(applicationId).isNotNull()
|
||||
assertThat(applicationId?.trim()).isNotEmpty()
|
||||
|
||||
// the build types don't have any applicationIdSuffix set
|
||||
// so only suffix from the flavors should be applied here
|
||||
assertThat(applicationId).isAnyOf("com.itsaky.test.app.full", "com.itsaky.test.app.demo")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test variant-specific application ID computation for build types with applicationIdSuffix`() {
|
||||
// only the build types have applicationIdSuffix set, not the product flavors
|
||||
val androidBlockConfig = """
|
||||
buildTypes {
|
||||
create("staging") {
|
||||
applicationIdSuffix = ".staging"
|
||||
}
|
||||
create("experimental") {
|
||||
applicationIdSuffix = ".experimental"
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
val client = ToolingApiTestLauncher.MultiVersionTestClient(
|
||||
androidBlockConfig = androidBlockConfig)
|
||||
val (_, project, initializeResult) = ToolingApiTestLauncher().launchServer(client = client)
|
||||
|
||||
assertThat(initializeResult).isNotNull()
|
||||
assertThat(initializeResult?.isSuccessful).isTrue()
|
||||
assertThat(initializeResult?.failure).isNull()
|
||||
|
||||
assertThat(project).isNotNull()
|
||||
|
||||
val selectionResult = project.selectProject(StringParameter(":app")).get()
|
||||
assertThat(selectionResult).isNotNull()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val app = project.asAndroidProject()
|
||||
assertThat(app).isNotNull()
|
||||
assertThat(app).isInstanceOf(IAndroidProject::class.java)
|
||||
|
||||
val variants = app.getVariants().get()
|
||||
assertThat(variants).isNotNull()
|
||||
assertThat(variants).isNotEmpty()
|
||||
|
||||
|
||||
assertThat(variants).hasSize(4)
|
||||
assertThat(variants.map { it.name }).containsExactly("debug", "release", "staging",
|
||||
"experimental")
|
||||
|
||||
variants.forEach { variant ->
|
||||
val applicationId = variant.mainArtifact.applicationId
|
||||
assertThat(applicationId).isNotNull()
|
||||
assertThat(applicationId?.trim()).isNotEmpty()
|
||||
assertThat(applicationId).isAnyOf("com.itsaky.test.app", "com.itsaky.test.app.staging",
|
||||
"com.itsaky.test.app.experimental")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test variant-specific application ID computation for build types with applicationIdSuffix and multiple product flavors`() {
|
||||
// only the flavors have applicationIdSuffix set, but additional build types have been created
|
||||
val androidBlockConfig = """
|
||||
flavorDimensions.add("default")
|
||||
|
||||
productFlavors {
|
||||
create("full") {
|
||||
dimension = "default"
|
||||
}
|
||||
create("demo") {
|
||||
dimension = "default"
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
create("staging") {
|
||||
applicationIdSuffix = ".staging"
|
||||
}
|
||||
create("experimental") {
|
||||
applicationIdSuffix = ".experimental"
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
val client = ToolingApiTestLauncher.MultiVersionTestClient(
|
||||
androidBlockConfig = androidBlockConfig)
|
||||
val (_, project, initializeResult) = ToolingApiTestLauncher().launchServer(client = client)
|
||||
|
||||
assertThat(initializeResult).isNotNull()
|
||||
assertThat(initializeResult?.isSuccessful).isTrue()
|
||||
assertThat(initializeResult?.failure).isNull()
|
||||
|
||||
assertThat(project).isNotNull()
|
||||
|
||||
val selectionResult = project.selectProject(StringParameter(":app")).get()
|
||||
assertThat(selectionResult).isNotNull()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val app = project.asAndroidProject()
|
||||
assertThat(app).isNotNull()
|
||||
assertThat(app).isInstanceOf(IAndroidProject::class.java)
|
||||
|
||||
val variants = app.getVariants().get()
|
||||
assertThat(variants).isNotNull()
|
||||
assertThat(variants).isNotEmpty()
|
||||
|
||||
|
||||
assertThat(variants).hasSize(8)
|
||||
assertThat(variants.map { it.name }).containsExactly("fullDebug", "fullRelease", "fullStaging",
|
||||
"fullExperimental", "demoDebug", "demoRelease", "demoStaging", "demoExperimental")
|
||||
|
||||
variants.forEach { variant ->
|
||||
val applicationId = variant.mainArtifact.applicationId
|
||||
assertThat(applicationId).isNotNull()
|
||||
assertThat(applicationId?.trim()).isNotEmpty()
|
||||
|
||||
// the flavors don't have any applicationIdSuffix set
|
||||
// so only suffix from the build types should be applied here
|
||||
assertThat(applicationId).isAnyOf("com.itsaky.test.app", "com.itsaky.test.app.staging",
|
||||
"com.itsaky.test.app.experimental")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test variant-specific application ID computation for build types and product flavors with applicationIdSuffix`() {
|
||||
// only the flavors have applicationIdSuffix set, but additional build types have been created
|
||||
val androidBlockConfig = """
|
||||
flavorDimensions.add("default")
|
||||
|
||||
productFlavors {
|
||||
create("full") {
|
||||
dimension = "default"
|
||||
applicationIdSuffix = ".full"
|
||||
}
|
||||
create("demo") {
|
||||
dimension = "default"
|
||||
applicationIdSuffix = ".demo"
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
create("staging") {
|
||||
applicationIdSuffix = ".staging"
|
||||
}
|
||||
create("experimental") {
|
||||
applicationIdSuffix = ".experimental"
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
val client = ToolingApiTestLauncher.MultiVersionTestClient(
|
||||
androidBlockConfig = androidBlockConfig)
|
||||
val (_, project, initializeResult) = ToolingApiTestLauncher().launchServer(client = client)
|
||||
|
||||
assertThat(initializeResult).isNotNull()
|
||||
assertThat(initializeResult?.isSuccessful).isTrue()
|
||||
assertThat(initializeResult?.failure).isNull()
|
||||
|
||||
assertThat(project).isNotNull()
|
||||
|
||||
val selectionResult = project.selectProject(StringParameter(":app")).get()
|
||||
assertThat(selectionResult).isNotNull()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val app = project.asAndroidProject()
|
||||
assertThat(app).isNotNull()
|
||||
assertThat(app).isInstanceOf(IAndroidProject::class.java)
|
||||
|
||||
val variants = app.getVariants().get()
|
||||
assertThat(variants).isNotNull()
|
||||
assertThat(variants).isNotEmpty()
|
||||
|
||||
|
||||
assertThat(variants).hasSize(8)
|
||||
assertThat(variants.map { it.name }).containsExactly("fullDebug", "fullRelease", "fullStaging",
|
||||
"fullExperimental", "demoDebug", "demoRelease", "demoStaging", "demoExperimental")
|
||||
|
||||
variants.forEach { variant ->
|
||||
val applicationId = variant.mainArtifact.applicationId
|
||||
assertThat(applicationId).isNotNull()
|
||||
assertThat(applicationId?.trim()).isNotEmpty()
|
||||
|
||||
// the flavors don't have any applicationIdSuffix set
|
||||
// so only suffix from the build types should be applied here
|
||||
assertThat(applicationId).isAnyOf(
|
||||
// 'debug' and 'release' build types
|
||||
"com.itsaky.test.app.full", "com.itsaky.test.app.demo",
|
||||
|
||||
// custom build types with applicationIdSuffix
|
||||
"com.itsaky.test.app.full.staging", "com.itsaky.test.app.demo.staging",
|
||||
"com.itsaky.test.app.full.experimental", "com.itsaky.test.app.demo.experimental")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test variant-specific application ID computation for product flavors with custom applicationId`() {
|
||||
// only the flavors have applicationIdSuffix set, not the build types
|
||||
val androidBlockConfig = """
|
||||
flavorDimensions.add("default")
|
||||
|
||||
productFlavors {
|
||||
create("full") {
|
||||
dimension = "default"
|
||||
applicationId = "com.androidide.app.full"
|
||||
}
|
||||
create("demo") {
|
||||
dimension = "default"
|
||||
applicationId = "com.androidide.app.demo"
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
val client = ToolingApiTestLauncher.MultiVersionTestClient(
|
||||
androidBlockConfig = androidBlockConfig)
|
||||
val (_, project, initializeResult) = ToolingApiTestLauncher().launchServer(client = client)
|
||||
|
||||
assertThat(initializeResult).isNotNull()
|
||||
assertThat(initializeResult?.isSuccessful).isTrue()
|
||||
assertThat(initializeResult?.failure).isNull()
|
||||
|
||||
assertThat(project).isNotNull()
|
||||
|
||||
val selectionResult = project.selectProject(StringParameter(":app")).get()
|
||||
assertThat(selectionResult).isNotNull()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val app = project.asAndroidProject()
|
||||
assertThat(app).isNotNull()
|
||||
assertThat(app).isInstanceOf(IAndroidProject::class.java)
|
||||
|
||||
val variants = app.getVariants().get()
|
||||
assertThat(variants).isNotNull()
|
||||
assertThat(variants).isNotEmpty()
|
||||
|
||||
|
||||
assertThat(variants).hasSize(4)
|
||||
assertThat(variants.map { it.name }).containsExactly("fullDebug", "fullRelease", "demoDebug",
|
||||
"demoRelease")
|
||||
|
||||
variants.forEach { variant ->
|
||||
val applicationId = variant.mainArtifact.applicationId
|
||||
assertThat(applicationId).isNotNull()
|
||||
assertThat(applicationId?.trim()).isNotEmpty()
|
||||
assertThat(applicationId).isAnyOf("com.androidide.app.full", "com.androidide.app.demo")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test variant-specific application ID computation for product flavors with custom applicationId and applicationIdSuffix`() {
|
||||
// only the flavors have applicationIdSuffix set, not the build types
|
||||
val androidBlockConfig = """
|
||||
flavorDimensions.add("default")
|
||||
|
||||
productFlavors {
|
||||
create("full") {
|
||||
dimension = "default"
|
||||
applicationId = "com.androidide.app.full"
|
||||
}
|
||||
create("demo") {
|
||||
dimension = "default"
|
||||
applicationIdSuffix = ".demo"
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
val client = ToolingApiTestLauncher.MultiVersionTestClient(
|
||||
androidBlockConfig = androidBlockConfig)
|
||||
val (_, project, initializeResult) = ToolingApiTestLauncher().launchServer(client = client)
|
||||
|
||||
assertThat(initializeResult).isNotNull()
|
||||
assertThat(initializeResult?.isSuccessful).isTrue()
|
||||
assertThat(initializeResult?.failure).isNull()
|
||||
|
||||
assertThat(project).isNotNull()
|
||||
|
||||
val selectionResult = project.selectProject(StringParameter(":app")).get()
|
||||
assertThat(selectionResult).isNotNull()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val app = project.asAndroidProject()
|
||||
assertThat(app).isNotNull()
|
||||
assertThat(app).isInstanceOf(IAndroidProject::class.java)
|
||||
|
||||
val variants = app.getVariants().get()
|
||||
assertThat(variants).isNotNull()
|
||||
assertThat(variants).isNotEmpty()
|
||||
|
||||
|
||||
assertThat(variants).hasSize(4)
|
||||
assertThat(variants.map { it.name }).containsExactly("fullDebug", "fullRelease", "demoDebug",
|
||||
"demoRelease")
|
||||
|
||||
variants.forEach { variant ->
|
||||
val applicationId = variant.mainArtifact.applicationId
|
||||
assertThat(applicationId).isNotNull()
|
||||
assertThat(applicationId?.trim()).isNotEmpty()
|
||||
assertThat(applicationId).isAnyOf("com.androidide.app.full", "com.itsaky.test.app.demo")
|
||||
}
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.tooling.impl
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.itsaky.androidide.builder.model.IDESyncIssue
|
||||
import com.itsaky.androidide.buildinfo.BuildInfo
|
||||
import com.itsaky.androidide.testing.common.CIOnlyTestRule
|
||||
import com.itsaky.androidide.testing.tooling.ToolingApiTestLauncher
|
||||
import com.itsaky.androidide.tooling.api.util.ToolingProps
|
||||
import com.itsaky.androidide.utils.AndroidPluginVersion
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.JUnit4
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
@RunWith(JUnit4::class)
|
||||
class CIOnlyToolingApiTests {
|
||||
|
||||
@JvmField
|
||||
@Rule
|
||||
val ciOnlyTestRule = CIOnlyTestRule()
|
||||
|
||||
/**
|
||||
* Tests the functionality of the tooling API implementation against multiple versions of the
|
||||
* Android Gradle Plugin. This test runs only in the CI environment.
|
||||
*/
|
||||
@Test
|
||||
fun `test CI-only simple multi module project initialization with multiple AGP versions`() {
|
||||
// Test the minimum supported and the latest AGP version
|
||||
val versions =
|
||||
listOf(
|
||||
// AGP to Gradle
|
||||
BuildInfo.AGP_VERSION_MININUM to "7.3.3",
|
||||
BuildInfo.AGP_VERSION_LATEST to "8.2"
|
||||
)
|
||||
|
||||
val client = ToolingApiTestLauncher.MultiVersionTestClient()
|
||||
for ((agpVersion, gradleVersion) in versions) {
|
||||
client.agpVersion = agpVersion
|
||||
client.gradleVersion = gradleVersion
|
||||
val (server, project, result) = ToolingApiTestLauncher().launchServer(client = client)
|
||||
assertThat(result?.isSuccessful).isTrue()
|
||||
|
||||
performBasicProjectAssertions(project = project, server = server)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test CI-only latest tested AGP version warning`() {
|
||||
val log = CollectingLogger()
|
||||
val agpVersion = AndroidPluginVersion.parse(BuildInfo.AGP_VERSION_LATEST)
|
||||
|
||||
val client = ToolingApiTestLauncher.MultiVersionTestClient(
|
||||
agpVersion = agpVersion.toStringSimple(),
|
||||
gradleVersion = "${agpVersion.major}.${agpVersion.minor}", log = log)
|
||||
val (_, project, result) = ToolingApiTestLauncher().launchServer(
|
||||
client = client,
|
||||
log = log,
|
||||
sysProps = mapOf(
|
||||
ToolingProps.TESTING_LATEST_AGP_VERSION to ToolingApiTestLauncher.MultiVersionTestClient.DEFAULT_AGP_VERSION)
|
||||
)
|
||||
val output = log.toString()
|
||||
|
||||
if (result?.isSuccessful != true) {
|
||||
// print the output if the initialization fails
|
||||
println(output)
|
||||
}
|
||||
|
||||
assertThat(result?.isSuccessful).isTrue()
|
||||
|
||||
val syncIssues = project.getProjectSyncIssues().get()
|
||||
assertThat(syncIssues).isNotNull()
|
||||
assertThat(syncIssues.syncIssues).isNotEmpty()
|
||||
assertThat(
|
||||
syncIssues.syncIssues.find { it.type == IDESyncIssue.TYPE_AGP_VERSION_TOO_NEW }
|
||||
).isNotNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test CI-only minimum AGP version failure`() {
|
||||
val log = CollectingLogger()
|
||||
val agpVersion = "7.1.0"
|
||||
val client = ToolingApiTestLauncher.MultiVersionTestClient(agpVersion = agpVersion,
|
||||
gradleVersion = "7.2", log = log)
|
||||
val (_, _, result) = ToolingApiTestLauncher().launchServer(client = client, log = log)
|
||||
assertThat(result?.isSuccessful).isFalse()
|
||||
|
||||
val output = log.toString()
|
||||
assertThat(output).contains(
|
||||
"Android Gradle Plugin version $agpVersion is not supported by AndroidIDE.")
|
||||
}
|
||||
}
|
||||
+4
-258
@@ -17,29 +17,13 @@
|
||||
|
||||
package com.itsaky.androidide.tooling.impl
|
||||
|
||||
import com.android.builder.model.v2.ide.LibraryType
|
||||
import com.android.builder.model.v2.ide.ProjectType.APPLICATION
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.itsaky.androidide.builder.model.IDESyncIssue
|
||||
import com.itsaky.androidide.buildinfo.BuildInfo
|
||||
import com.itsaky.androidide.tooling.api.IAndroidProject
|
||||
import com.itsaky.androidide.tooling.api.IJavaProject
|
||||
import com.itsaky.androidide.tooling.api.IProject
|
||||
import com.itsaky.androidide.tooling.api.IToolingApiServer
|
||||
import com.itsaky.androidide.tooling.api.ProjectType
|
||||
import com.itsaky.androidide.testing.tooling.ToolingApiTestLauncher
|
||||
import com.itsaky.androidide.testing.tooling.ToolingApiTestLauncher.MultiVersionTestClient
|
||||
import com.itsaky.androidide.tooling.api.messages.TaskExecutionMessage
|
||||
import com.itsaky.androidide.tooling.api.messages.result.TaskExecutionResult
|
||||
import com.itsaky.androidide.tooling.api.models.AndroidProjectMetadata
|
||||
import com.itsaky.androidide.tooling.api.models.JavaModuleExternalDependency
|
||||
import com.itsaky.androidide.tooling.api.models.JavaModuleProjectDependency
|
||||
import com.itsaky.androidide.tooling.api.models.JavaProjectMetadata
|
||||
import com.itsaky.androidide.tooling.api.models.params.StringParameter
|
||||
import com.itsaky.androidide.tooling.events.ProgressEvent
|
||||
import com.itsaky.androidide.tooling.events.task.TaskStartEvent
|
||||
import com.itsaky.androidide.tooling.api.util.ToolingProps
|
||||
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher
|
||||
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher.MultiVersionTestClient
|
||||
import com.itsaky.androidide.utils.AndroidPluginVersion
|
||||
import com.itsaky.androidide.utils.FileProvider
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import org.junit.Test
|
||||
@@ -60,7 +44,7 @@ class MultiModuleAndroidProjectTest {
|
||||
fun `test simple multi module project initialization`() {
|
||||
val (server, project, result) = ToolingApiTestLauncher().launchServer()
|
||||
assertThat(result?.isSuccessful).isTrue()
|
||||
doAssertions(project, server)
|
||||
performBasicProjectAssertions(project, server)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -91,7 +75,7 @@ class MultiModuleAndroidProjectTest {
|
||||
|
||||
val taskPaths = mutableListOf<String>()
|
||||
|
||||
// do not add unresolved dependency so that teh configuration cache is properly created
|
||||
// do not add unresolved dependency so that the configuration cache is properly created
|
||||
val client = object : MultiVersionTestClient(excludeUnresolvedDependency = true) {
|
||||
|
||||
override fun getBuildArguments(): CompletableFuture<List<String>> {
|
||||
@@ -159,242 +143,4 @@ class MultiModuleAndroidProjectTest {
|
||||
assertThat(initResult!!.isSuccessful).isFalse()
|
||||
assertThat(initResult.failure).isEqualTo(TaskExecutionResult.Failure.BUILD_CANCELLED)
|
||||
}
|
||||
|
||||
private fun doAssertions(project: IProject, server: IToolingApiServer) {
|
||||
assertThat(project).isNotNull()
|
||||
|
||||
// As the returned project is just a proxy,
|
||||
// project instanceOf IdeGradleProject will always return false
|
||||
val isInitialized = server.isServerInitialized().get()
|
||||
assertThat(isInitialized).isTrue()
|
||||
|
||||
var selectionResult = project.selectProject(StringParameter("")).get()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
assertThat(project.getType().get()).isEqualTo(ProjectType.Gradle)
|
||||
|
||||
selectionResult = project.selectProject(StringParameter(":app")).get()
|
||||
assertThat(selectionResult).isNotNull()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val app = project.asAndroidProject()
|
||||
assertThat(app).isNotNull()
|
||||
assertThat(app).isInstanceOf(IAndroidProject::class.java)
|
||||
|
||||
var metadata = app.getMetadata().get() as AndroidProjectMetadata
|
||||
assertThat(metadata).isNotNull()
|
||||
assertThat(metadata.javaCompileOptions.sourceCompatibility).isEqualTo("11")
|
||||
assertThat(metadata.javaCompileOptions.targetCompatibility).isEqualTo("11")
|
||||
assertThat(metadata.javaCompileOptions.javaSourceVersion).isEqualTo("11")
|
||||
assertThat(metadata.javaCompileOptions.javaBytecodeVersion).isEqualTo("11")
|
||||
assertThat(metadata.javaCompileOptions.isCoreLibraryDesugaringEnabled).isFalse()
|
||||
assertThat(metadata.androidType).isEqualTo(APPLICATION)
|
||||
assertThat(metadata.packageName).isEqualTo("com.itsaky.test.app")
|
||||
assertThat(metadata.viewBindingOptions).isNotNull()
|
||||
assertThat(metadata.viewBindingOptions.isEnabled).isTrue()
|
||||
|
||||
// There are always more than 100 tasks in an android module
|
||||
// Also, the tasks must contain the user defined tasks
|
||||
val tasks = app.getTasks().get()
|
||||
assertThat(tasks.size).isAtLeast(100)
|
||||
assertThat(tasks.first { it.path == "${metadata.projectPath}:thisIsATestTask" }).isNotNull()
|
||||
|
||||
var libraries = app.getLibraryMap().get()
|
||||
// At least one project library
|
||||
assertThat(libraries.values.filter { it.type == LibraryType.PROJECT }).isNotEmpty()
|
||||
// :app module includes :java-library as a dependency. But it is not transitive
|
||||
assertThat(
|
||||
libraries.values.firstOrNull {
|
||||
it.type == LibraryType.PROJECT &&
|
||||
it.projectInfo!!.projectPath == ":another-java-library" &&
|
||||
it.projectInfo!!.attributes["org.gradle.usage"] == "java-api"
|
||||
}
|
||||
)
|
||||
.isNull()
|
||||
|
||||
selectionResult = project.selectProject(StringParameter(":android-library")).get()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val androidLib = project.asAndroidProject()
|
||||
assertThat(androidLib).isNotNull()
|
||||
assertThat(androidLib).isInstanceOf(IAndroidProject::class.java)
|
||||
// Make sure that transitive dependencies are included here because :android-library includes
|
||||
// :java-library project which further includes :another-java-libraries project with 'api'
|
||||
// configuration
|
||||
libraries = androidLib.getLibraryMap().get()!!
|
||||
assertThat(
|
||||
libraries.values.firstOrNull {
|
||||
it.type == LibraryType.PROJECT &&
|
||||
it.projectInfo!!.projectPath == ":another-java-library" &&
|
||||
it.projectInfo!!.attributes["org.gradle.usage"] == "java-api"
|
||||
}
|
||||
)
|
||||
.isNotNull()
|
||||
|
||||
metadata = androidLib.getMetadata().get() as AndroidProjectMetadata
|
||||
assertThat(metadata.javaCompileOptions.javaSourceVersion).isEqualTo("11")
|
||||
assertThat(metadata.javaCompileOptions.javaBytecodeVersion).isEqualTo("11")
|
||||
|
||||
selectionResult = project.selectProject(StringParameter(":java-library")).get()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val javaLibrary = project.asJavaProject()
|
||||
assertThat(javaLibrary).isNotNull()
|
||||
assertThat(javaLibrary).isInstanceOf(IJavaProject::class.java)
|
||||
|
||||
var javaMetadata = javaLibrary.getMetadata().get() as JavaProjectMetadata
|
||||
assertThat(javaMetadata.compilerSettings.javaSourceVersion).isEqualTo("11")
|
||||
assertThat(javaMetadata.compilerSettings.javaBytecodeVersion).isEqualTo("11")
|
||||
|
||||
val javaDependencies = javaLibrary.getDependencies().get()
|
||||
assertThat(
|
||||
javaDependencies.firstOrNull {
|
||||
it is JavaModuleExternalDependency &&
|
||||
it.gradleArtifact != null &&
|
||||
it.run {
|
||||
gradleArtifact!!.group == "io.github.itsaky" &&
|
||||
gradleArtifact!!.name == "nb-javac-android" &&
|
||||
gradleArtifact!!.version == "17.0.0.0"
|
||||
}
|
||||
}
|
||||
)
|
||||
.isNotNull()
|
||||
assertThat(
|
||||
javaDependencies.firstOrNull {
|
||||
it is JavaModuleProjectDependency && it.moduleName == "another-java-library"
|
||||
}
|
||||
)
|
||||
.isNotNull()
|
||||
// In case we have multiple dependencies with same name but different path
|
||||
val nested =
|
||||
javaDependencies
|
||||
.filterIsInstance(JavaModuleProjectDependency::class.java)
|
||||
.filter { it.moduleName.endsWith("nested-java-library") }
|
||||
assertThat(nested).hasSize(2)
|
||||
assertThat(nested[0].projectPath).isNotEqualTo(nested[1].projectPath)
|
||||
assertThat(
|
||||
project.selectProject(StringParameter(":does-not-exist")).get().isSuccessful).isFalse()
|
||||
|
||||
selectionResult = project.selectProject(StringParameter(":another-java-library")).get()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val anotherJavaLib = project.asJavaProject()
|
||||
assertThat(anotherJavaLib).isNotNull()
|
||||
assertThat(anotherJavaLib).isInstanceOf(IJavaProject::class.java)
|
||||
|
||||
javaMetadata = anotherJavaLib.getMetadata().get() as JavaProjectMetadata
|
||||
assertThat(javaMetadata.compilerSettings.javaSourceVersion).isEqualTo("1.8")
|
||||
assertThat(javaMetadata.compilerSettings.javaBytecodeVersion).isEqualTo("1.8")
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the functionality of the tooling API implementation against multiple versions of the
|
||||
* Android Gradle Plugin. This test runs only in the CI environment.
|
||||
*/
|
||||
@Test
|
||||
@Throws(CIOnlyException::class)
|
||||
fun `test CI-only simple multi module project initialization with multiple AGP versions`() {
|
||||
ciOnlyTest {
|
||||
// Test the minimum supported and the latest AGP version
|
||||
val versions =
|
||||
listOf(
|
||||
// AGP to Gradle
|
||||
BuildInfo.AGP_VERSION_MININUM to "7.3.3",
|
||||
BuildInfo.AGP_VERSION_LATEST to "8.2"
|
||||
)
|
||||
|
||||
val client = MultiVersionTestClient()
|
||||
for ((agpVersion, gradleVersion) in versions) {
|
||||
client.agpVersion = agpVersion
|
||||
client.gradleVersion = gradleVersion
|
||||
val (server, project, result) = ToolingApiTestLauncher().launchServer(client = client)
|
||||
assertThat(result?.isSuccessful).isTrue()
|
||||
doAssertions(project = project, server = server)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(CIOnlyException::class)
|
||||
fun `test CI-only latest tested AGP version warning`() {
|
||||
ciOnlyTest {
|
||||
val log = CollectingLogger()
|
||||
val agpVersion = AndroidPluginVersion.parse(BuildInfo.AGP_VERSION_LATEST)
|
||||
|
||||
val client = MultiVersionTestClient(agpVersion = agpVersion.toStringSimple(),
|
||||
gradleVersion = "${agpVersion.major}.${agpVersion.minor}", log = log)
|
||||
val (_, project, result) = ToolingApiTestLauncher().launchServer(
|
||||
client = client,
|
||||
log = log,
|
||||
sysProps = mapOf(
|
||||
ToolingProps.TESTING_LATEST_AGP_VERSION to MultiVersionTestClient.DEFAULT_AGP_VERSION)
|
||||
)
|
||||
val output = log.toString()
|
||||
|
||||
if (result?.isSuccessful != true) {
|
||||
// print the output if the initialization fails
|
||||
println(output)
|
||||
}
|
||||
|
||||
assertThat(result?.isSuccessful).isTrue()
|
||||
|
||||
val syncIssues = project.getProjectSyncIssues().get()
|
||||
assertThat(syncIssues).isNotNull()
|
||||
assertThat(syncIssues.syncIssues).isNotEmpty()
|
||||
assertThat(
|
||||
syncIssues.syncIssues.find { it.type == IDESyncIssue.TYPE_AGP_VERSION_TOO_NEW }
|
||||
).isNotNull()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(CIOnlyException::class)
|
||||
fun `test CI-only minimum AGP version failure`() {
|
||||
ciOnlyTest {
|
||||
val log = CollectingLogger()
|
||||
val agpVersion = "7.1.0"
|
||||
val client = MultiVersionTestClient(agpVersion = agpVersion, gradleVersion = "7.2", log = log)
|
||||
val (_, _, result) = ToolingApiTestLauncher().launchServer(client = client, log = log)
|
||||
assertThat(result?.isSuccessful).isFalse()
|
||||
|
||||
val output = log.toString()
|
||||
assertThat(output).contains(
|
||||
"Android Gradle Plugin version $agpVersion is not supported by AndroidIDE.")
|
||||
}
|
||||
}
|
||||
|
||||
private fun ciOnlyTest(test: () -> Unit) {
|
||||
try {
|
||||
assertIsCI()
|
||||
test()
|
||||
} catch (err: CIOnlyException) {
|
||||
if (shouldTestMultipleVersions()) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun assertIsCI() {
|
||||
if (!shouldTestMultipleVersions()) {
|
||||
throw CIOnlyException()
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldTestMultipleVersions(): Boolean {
|
||||
return System.getenv("TEST_TOOLING_API_IMPL").let { it == "true" }
|
||||
}
|
||||
|
||||
internal class CollectingLogger : ILogger(CollectingLogger::class.simpleName) {
|
||||
|
||||
private val string = StringBuilder()
|
||||
|
||||
override fun doLog(level: Level?, message: String?) {
|
||||
string.append("${message?.trim()}${System.lineSeparator()}")
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return string.toString()
|
||||
}
|
||||
}
|
||||
|
||||
private class CIOnlyException : IllegalStateException()
|
||||
}
|
||||
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.tooling.impl
|
||||
|
||||
import com.android.builder.model.v2.ide.LibraryType
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.itsaky.androidide.tooling.api.IAndroidProject
|
||||
import com.itsaky.androidide.tooling.api.IJavaProject
|
||||
import com.itsaky.androidide.tooling.api.IProject
|
||||
import com.itsaky.androidide.tooling.api.IToolingApiServer
|
||||
import com.itsaky.androidide.tooling.api.ProjectType
|
||||
import com.itsaky.androidide.tooling.api.models.AndroidProjectMetadata
|
||||
import com.itsaky.androidide.tooling.api.models.JavaModuleExternalDependency
|
||||
import com.itsaky.androidide.tooling.api.models.JavaModuleProjectDependency
|
||||
import com.itsaky.androidide.tooling.api.models.JavaProjectMetadata
|
||||
import com.itsaky.androidide.tooling.api.models.params.StringParameter
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
|
||||
internal class CollectingLogger : ILogger(CollectingLogger::class.simpleName) {
|
||||
|
||||
private val string = StringBuilder()
|
||||
|
||||
override fun doLog(level: Level?, message: String?) {
|
||||
string.append("${message?.trim()}${System.lineSeparator()}")
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return string.toString()
|
||||
}
|
||||
}
|
||||
|
||||
internal fun performBasicProjectAssertions(project: IProject, server: IToolingApiServer) {
|
||||
assertThat(project).isNotNull()
|
||||
|
||||
// As the returned project is just a proxy,
|
||||
// project instanceOf IdeGradleProject will always return false
|
||||
val isInitialized = server.isServerInitialized().get()
|
||||
assertThat(isInitialized).isTrue()
|
||||
|
||||
var selectionResult = project.selectProject(StringParameter("")).get()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
assertThat(project.getType().get()).isEqualTo(ProjectType.Gradle)
|
||||
|
||||
selectionResult = project.selectProject(StringParameter(":app")).get()
|
||||
assertThat(selectionResult).isNotNull()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val app = project.asAndroidProject()
|
||||
assertThat(app).isNotNull()
|
||||
assertThat(app).isInstanceOf(IAndroidProject::class.java)
|
||||
|
||||
var metadata = app.getMetadata().get() as AndroidProjectMetadata
|
||||
assertThat(metadata).isNotNull()
|
||||
assertThat(metadata.javaCompileOptions.sourceCompatibility).isEqualTo("11")
|
||||
assertThat(metadata.javaCompileOptions.targetCompatibility).isEqualTo("11")
|
||||
assertThat(metadata.javaCompileOptions.javaSourceVersion).isEqualTo("11")
|
||||
assertThat(metadata.javaCompileOptions.javaBytecodeVersion).isEqualTo("11")
|
||||
assertThat(metadata.javaCompileOptions.isCoreLibraryDesugaringEnabled).isFalse()
|
||||
assertThat(metadata.androidType)
|
||||
.isEqualTo(com.android.builder.model.v2.ide.ProjectType.APPLICATION)
|
||||
assertThat(metadata.packageName).isEqualTo("com.itsaky.test.app")
|
||||
assertThat(metadata.viewBindingOptions).isNotNull()
|
||||
assertThat(metadata.viewBindingOptions.isEnabled).isTrue()
|
||||
|
||||
// There are always more than 100 tasks in an android module
|
||||
// Also, the tasks must contain the user defined tasks
|
||||
val tasks = app.getTasks().get()
|
||||
assertThat(tasks.size).isAtLeast(100)
|
||||
assertThat(tasks.first { it.path == "${metadata.projectPath}:thisIsATestTask" }).isNotNull()
|
||||
|
||||
var libraries = app.getLibraryMap().get()
|
||||
// At least one project library
|
||||
assertThat(libraries.values.filter { it.type == LibraryType.PROJECT }).isNotEmpty()
|
||||
// :app module includes :java-library as a dependency. But it is not transitive
|
||||
assertThat(
|
||||
libraries.values.firstOrNull {
|
||||
it.type == LibraryType.PROJECT &&
|
||||
it.projectInfo!!.projectPath == ":another-java-library" &&
|
||||
it.projectInfo!!.attributes["org.gradle.usage"] == "java-api"
|
||||
}
|
||||
)
|
||||
.isNull()
|
||||
|
||||
selectionResult = project.selectProject(StringParameter(":android-library")).get()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val androidLib = project.asAndroidProject()
|
||||
assertThat(androidLib).isNotNull()
|
||||
assertThat(androidLib).isInstanceOf(IAndroidProject::class.java)
|
||||
// Make sure that transitive dependencies are included here because :android-library includes
|
||||
// :java-library project which further includes :another-java-libraries project with 'api'
|
||||
// configuration
|
||||
libraries = androidLib.getLibraryMap().get()!!
|
||||
assertThat(
|
||||
libraries.values.firstOrNull {
|
||||
it.type == LibraryType.PROJECT &&
|
||||
it.projectInfo!!.projectPath == ":another-java-library" &&
|
||||
it.projectInfo!!.attributes["org.gradle.usage"] == "java-api"
|
||||
}
|
||||
)
|
||||
.isNotNull()
|
||||
|
||||
metadata = androidLib.getMetadata().get() as AndroidProjectMetadata
|
||||
assertThat(metadata.javaCompileOptions.javaSourceVersion).isEqualTo("11")
|
||||
assertThat(metadata.javaCompileOptions.javaBytecodeVersion).isEqualTo("11")
|
||||
|
||||
selectionResult = project.selectProject(StringParameter(":java-library")).get()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val javaLibrary = project.asJavaProject()
|
||||
assertThat(javaLibrary).isNotNull()
|
||||
assertThat(javaLibrary).isInstanceOf(IJavaProject::class.java)
|
||||
|
||||
var javaMetadata = javaLibrary.getMetadata().get() as JavaProjectMetadata
|
||||
assertThat(javaMetadata.compilerSettings.javaSourceVersion).isEqualTo("11")
|
||||
assertThat(javaMetadata.compilerSettings.javaBytecodeVersion).isEqualTo("11")
|
||||
|
||||
val javaDependencies = javaLibrary.getDependencies().get()
|
||||
assertThat(
|
||||
javaDependencies.firstOrNull {
|
||||
it is JavaModuleExternalDependency &&
|
||||
it.gradleArtifact != null &&
|
||||
it.run {
|
||||
gradleArtifact!!.group == "io.github.itsaky" &&
|
||||
gradleArtifact!!.name == "nb-javac-android" &&
|
||||
gradleArtifact!!.version == "17.0.0.0"
|
||||
}
|
||||
}
|
||||
)
|
||||
.isNotNull()
|
||||
assertThat(
|
||||
javaDependencies.firstOrNull {
|
||||
it is JavaModuleProjectDependency && it.moduleName == "another-java-library"
|
||||
}
|
||||
)
|
||||
.isNotNull()
|
||||
// In case we have multiple dependencies with same name but different path
|
||||
val nested =
|
||||
javaDependencies
|
||||
.filterIsInstance(JavaModuleProjectDependency::class.java)
|
||||
.filter { it.moduleName.endsWith("nested-java-library") }
|
||||
assertThat(nested).hasSize(2)
|
||||
assertThat(nested[0].projectPath).isNotEqualTo(nested[1].projectPath)
|
||||
assertThat(
|
||||
project.selectProject(StringParameter(":does-not-exist")).get().isSuccessful).isFalse()
|
||||
|
||||
selectionResult = project.selectProject(StringParameter(":another-java-library")).get()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val anotherJavaLib = project.asJavaProject()
|
||||
assertThat(anotherJavaLib).isNotNull()
|
||||
assertThat(anotherJavaLib).isInstanceOf(IJavaProject::class.java)
|
||||
|
||||
javaMetadata = anotherJavaLib.getMetadata().get() as JavaProjectMetadata
|
||||
assertThat(javaMetadata.compilerSettings.javaSourceVersion).isEqualTo("1.8")
|
||||
assertThat(javaMetadata.compilerSettings.javaBytecodeVersion).isEqualTo("1.8")
|
||||
}
|
||||
+1
@@ -27,6 +27,7 @@ import java.io.Serializable
|
||||
*/
|
||||
data class AndroidArtifactMetadata(
|
||||
val name: String,
|
||||
val applicationId: String?,
|
||||
val resGenTaskName: String?,
|
||||
val assembleTaskOutputListingFile: File?,
|
||||
val generatedResourceFolders: Collection<File>,
|
||||
|
||||
+1
-1
@@ -23,4 +23,4 @@ package com.itsaky.androidide.tooling.api.messages.result
|
||||
* @param isSuccessful Whether the project initialization was successful.
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class InitializeResult(val isSuccessful: Boolean, val failure: TaskExecutionResult.Failure? = TaskExecutionResult.Failure.UNKNOWN)
|
||||
class InitializeResult(val isSuccessful: Boolean, val failure: TaskExecutionResult.Failure? = null)
|
||||
|
||||
@@ -39,6 +39,8 @@ dependencies {
|
||||
exclude("org.jetbrains.kotlin")
|
||||
}
|
||||
|
||||
api(projects.testing.common)
|
||||
|
||||
api(projects.buildInfo)
|
||||
api(projects.common)
|
||||
api(projects.shared)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
/build
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
//noinspection JavaPluginLanguageLevel
|
||||
id("java-library")
|
||||
alias(libs.plugins.kotlin.jvm)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(libs.tests.junit)
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.itsaky.androidide.testing.common
|
||||
|
||||
import org.junit.rules.TestRule
|
||||
import org.junit.runner.Description
|
||||
import org.junit.runners.model.Statement
|
||||
|
||||
/**
|
||||
* A [TestRule] which only runs the tests in a CI environment.
|
||||
*/
|
||||
class CIOnlyTestRule : TestRule {
|
||||
|
||||
override fun apply(base: Statement, description: Description?): Statement {
|
||||
return object : Statement() {
|
||||
override fun evaluate() {
|
||||
if (isCi()) {
|
||||
base.evaluate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isCi() = System.getenv("CI").toBoolean()
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.testing.common
|
||||
|
||||
import org.junit.runners.model.Statement
|
||||
|
||||
/**
|
||||
* A no-op statement.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class NoOpStatement : Statement() {
|
||||
|
||||
override fun evaluate() {
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@ dependencies {
|
||||
api(projects.eventbusAndroid)
|
||||
|
||||
api(libs.common.editor)
|
||||
api(projects.testing.common)
|
||||
api(projects.testing.tooling)
|
||||
api(projects.testing.unit)
|
||||
}
|
||||
@@ -35,8 +35,7 @@ import com.itsaky.androidide.projects.ProjectManagerImpl
|
||||
import com.itsaky.androidide.projects.builder.BuildService
|
||||
import com.itsaky.androidide.tooling.api.IProject
|
||||
import com.itsaky.androidide.tooling.api.IToolingApiServer
|
||||
import com.itsaky.androidide.tooling.api.messages.InitializeProjectParams
|
||||
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher
|
||||
import com.itsaky.androidide.testing.tooling.ToolingApiTestLauncher
|
||||
import com.itsaky.androidide.utils.Environment
|
||||
import com.itsaky.androidide.utils.FileProvider
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
|
||||
@@ -34,6 +34,8 @@ android {
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
|
||||
@@ANDROID_BLOCK_CONFIG@@
|
||||
}
|
||||
|
||||
task thisIsATestTask () {
|
||||
|
||||
@@ -33,6 +33,8 @@ dependencies {
|
||||
api(projects.shared)
|
||||
api(projects.subprojects.toolingApi)
|
||||
|
||||
api(projects.testing.common)
|
||||
|
||||
// build tooling API before tests
|
||||
compileOnly(projects.subprojects.toolingApiImpl)
|
||||
}
|
||||
+8
-6
@@ -15,7 +15,7 @@
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.tooling.testing
|
||||
package com.itsaky.androidide.testing.tooling
|
||||
|
||||
import com.itsaky.androidide.tooling.api.IProject
|
||||
import com.itsaky.androidide.tooling.api.IToolingApiClient
|
||||
@@ -164,6 +164,7 @@ class ToolingApiTestLauncher {
|
||||
private val projectDir: Path = FileProvider.testProjectRoot(),
|
||||
var agpVersion: String = DEFAULT_AGP_VERSION,
|
||||
var gradleVersion: String = DEFAULT_GRADLE_VERSION,
|
||||
private val androidBlockConfig: String = "",
|
||||
private val log: ILogger = ILogger.newInstance(MultiVersionTestClient::class.simpleName),
|
||||
private val extraArgs: List<String> = emptyList(),
|
||||
private var excludeUnresolvedDependency: Boolean = false
|
||||
@@ -206,11 +207,12 @@ class ToolingApiTestLauncher {
|
||||
.replaceContents(dest = projectDir.resolve(buildFile),
|
||||
candidate = "@@TOOLING_API_TEST_AGP_VERSION@@" to this.agpVersion)
|
||||
|
||||
if (!excludeUnresolvedDependency) {
|
||||
projectDir.resolve(appBuildFileIn)
|
||||
.replaceContents(dest = projectDir.resolve(appBuildFile),
|
||||
candidate = "@@UNRESOLVED_DEPENDENCY@@" to "implementation 'unresolved:unresolved:unresolved'")
|
||||
}
|
||||
projectDir.resolve(appBuildFileIn)
|
||||
.replaceContents(
|
||||
projectDir.resolve(appBuildFile),
|
||||
"//",
|
||||
"@@ANDROID_BLOCK_CONFIG@@" to androidBlockConfig,
|
||||
"@@UNRESOLVED_DEPENDENCY@@" to if (!excludeUnresolvedDependency) "implementation 'unresolved:unresolved:unresolved'" else "")
|
||||
}
|
||||
|
||||
override fun onBuildSuccessful(result: BuildResult) {
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.tooling.testing
|
||||
package com.itsaky.androidide.testing.tooling
|
||||
|
||||
fun findAndroidHome(): String {
|
||||
var androidHome = System.getenv("ANDROID_HOME")
|
||||
@@ -34,4 +34,6 @@ dependencies {
|
||||
api(projects.buildInfo)
|
||||
api(projects.common)
|
||||
api(projects.shared)
|
||||
|
||||
api(projects.testing.common)
|
||||
}
|
||||
@@ -26,7 +26,7 @@ import com.itsaky.androidide.projects.IProjectManager
|
||||
import com.itsaky.androidide.projects.api.AndroidModule
|
||||
import com.itsaky.androidide.projects.builder.BuildService
|
||||
import com.itsaky.androidide.projects.util.findAppModule
|
||||
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher
|
||||
import com.itsaky.androidide.testing.tooling.ToolingApiTestLauncher
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Ignore
|
||||
import org.robolectric.Robolectric
|
||||
|
||||
Reference in New Issue
Block a user