Skip to content
Open
Show file tree
Hide file tree
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
Expand Up @@ -238,29 +238,19 @@ class FladlePluginDelegate {

androidComponents.onVariants { variant ->
if (!variant.isExpectedVariant(config)) return@onVariants
val androidTest = (variant as? HasAndroidTest)?.androidTest ?: return@onVariants
if ((variant as? HasAndroidTest)?.androidTest == null) return@onVariants

val buildType = variant.buildType ?: return@onVariants
val flavorName = variant.productFlavors.joinToString("") { it.second }
val flavorPath = variant.productFlavors.joinToString("/") { it.second }
val archivesName =
project.extensions
.getByType(BasePluginExtension::class.java)
.archivesName
.get()
val buildDir = project.layout.buildDirectory

// Test APK path
val testApkDirPath = if (flavorPath.isNotEmpty()) "androidTest/$flavorPath/$buildType" else "androidTest/$buildType"
val testApkFileName =
if (flavorName.isNotEmpty()) {
"$archivesName-$flavorName-$buildType-androidTest.apk"
} else {
"$archivesName-$buildType-androidTest.apk"
}
val testApkPath =
buildDir
.file("outputs/apk/$testApkDirPath/$testApkFileName")
.file("outputs/apk/${variant.androidTestApkPath(archivesName, buildType)}")
.get()
.asFile
.absolutePath
Expand All @@ -271,17 +261,9 @@ class FladlePluginDelegate {
val abiFilter = output.filters.firstOrNull { it.filterType == FilterConfiguration.FilterType.ABI }
val abiName = abiFilter?.identifier

val appApkDirPath = if (flavorPath.isNotEmpty()) "$flavorPath/$buildType" else buildType
val appApkFileName =
buildString {
append(archivesName)
if (flavorName.isNotEmpty()) append("-$flavorName")
if (abiName != null) append("-$abiName")
append("-$buildType.apk")
}
val appApkPath =
buildDir
.file("outputs/apk/$appApkDirPath/$appApkFileName")
.file("outputs/apk/${variant.appApkPath(archivesName, buildType, abiName)}")
.get()
.asFile
.absolutePath
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,39 +30,21 @@ class FulladlePlugin : Plugin<Project> {
androidComponents.onVariants { variant ->
val androidTest = (variant as? HasAndroidTest)?.androidTest ?: return@onVariants
val buildType = variant.buildType ?: return@onVariants
val flavorName = variant.productFlavors.joinToString("") { it.second }
val flavorPath = variant.productFlavors.joinToString("/") { it.second }
val archivesName = extensions.getByType(BasePluginExtension::class.java).archivesName.get()

variant.outputs.forEach { output ->
val abiFilter = output.filters.firstOrNull { it.filterType == FilterConfiguration.FilterType.ABI }
val abiName = abiFilter?.identifier

val appApkDirPath = if (flavorPath.isNotEmpty()) "$flavorPath/$buildType" else buildType
val appApkFileName =
buildString {
append(archivesName)
if (flavorName.isNotEmpty()) append("-$flavorName")
if (abiName != null) append("-$abiName")
append("-$buildType.apk")
}
val appApkPath =
layout.buildDirectory
.file("outputs/apk/$appApkDirPath/$appApkFileName")
.file("outputs/apk/${variant.appApkPath(archivesName, buildType, abiName)}")
.get()
.asFile.absolutePath

val testApkDirPath =
if (flavorPath.isNotEmpty()) "androidTest/$flavorPath/$buildType" else "androidTest/$buildType"
val testApkFileName =
if (flavorName.isNotEmpty()) {
"$archivesName-$flavorName-$buildType-androidTest.apk"
} else {
"$archivesName-$buildType-androidTest.apk"
}
val testApkPath =
layout.buildDirectory
.file("outputs/apk/$testApkDirPath/$testApkFileName")
.file("outputs/apk/${variant.androidTestApkPath(archivesName, buildType)}")
.get()
.asFile.absolutePath

Expand All @@ -84,21 +66,11 @@ class FulladlePlugin : Plugin<Project> {
androidComponents.onVariants { variant ->
val androidTest = (variant as? HasAndroidTest)?.androidTest ?: return@onVariants
val buildType = variant.buildType ?: return@onVariants
val flavorName = variant.productFlavors.joinToString("") { it.second }
val flavorPath = variant.productFlavors.joinToString("/") { it.second }
val archivesName = extensions.getByType(BasePluginExtension::class.java).archivesName.get()

val testApkDirPath =
if (flavorPath.isNotEmpty()) "androidTest/$flavorPath/$buildType" else "androidTest/$buildType"
val testApkFileName =
if (flavorName.isNotEmpty()) {
"$archivesName-$flavorName-$buildType-androidTest.apk"
} else {
"$archivesName-$buildType-androidTest.apk"
}
val testApkPath =
layout.buildDirectory
.file("outputs/apk/$testApkDirPath/$testApkFileName")
.file("outputs/apk/${variant.androidTestApkPath(archivesName, buildType)}")
.get()
.asFile.absolutePath

Expand Down
48 changes: 41 additions & 7 deletions fladle-plugin/src/main/java/com/osacky/flank/gradle/Variants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,44 @@ fun VariantOutput.isExpectedAbiOutput(config: FladleConfig): Boolean {
abiFilters.any { it.identifier == config.abi.get() }
}

/**
* Returns true if this [Variant] matches the variant specified in the [config].
*
* If no variant is specified, all variants are considered a match.
*/
fun Variant.isExpectedVariantInModule(config: FulladleModuleExtension) =
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

unused

!config.variant.isPresent || (config.variant.isPresent && this.name.contains(config.variant.get()))
fun Variant.appApkPath(
archivesName: String,
buildType: String,
abiName: String?,
): String = "${apkDirPath(buildType)}/${appApkFileName(archivesName, buildType, abiName)}"

fun Variant.androidTestApkPath(
archivesName: String,
buildType: String,
): String = "androidTest/${apkDirPath(buildType)}/${androidTestApkFileName(archivesName, buildType)}"

private fun Variant.apkDirPath(buildType: String): String {
val flavorPath = flavorName.orEmpty()
return if (flavorPath.isNotEmpty()) "$flavorPath/$buildType" else buildType
}

private fun Variant.appApkFileName(
archivesName: String,
buildType: String,
abiName: String?,
): String =
buildString {
append(archivesName)
val flavorName = flavorFileName()
if (flavorName.isNotEmpty()) append("-$flavorName")
if (abiName != null) append("-$abiName")
append("-$buildType.apk")
}

private fun Variant.androidTestApkFileName(
archivesName: String,
buildType: String,
): String =
buildString {
append(archivesName)
val flavorName = flavorFileName()
if (flavorName.isNotEmpty()) append("-$flavorName")
append("-$buildType-androidTest.apk")
}

private fun Variant.flavorFileName(): String = productFlavors.joinToString("-") { it.second }
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,50 @@ class AutoConfigureFladleTest {
""".trimIndent(),
)
}

@Test
fun testAndroidProjectWithMultipleFlavorDimensions() {
val fixtureName = "android-project-multiple-flavor-dimensions"
testProjectRoot.newFile("local.properties").writeText("sdk.dir=${androidHome()}\n")
testProjectRoot.newFile("gradle.properties").writeText("android.useAndroidX=true")
writeBuildGradle(
"""
allprojects {
repositories {
google()
mavenCentral()
}
}
""".trimIndent(),
)
testProjectRoot.newFile("settings.gradle").writeText(
"""
include '$fixtureName'
""".trimIndent(),
)

testProjectRoot.setupFixture(fixtureName)

val result =
GradleRunner
.create()
.withProjectDir(testProjectRoot.root)
.withPluginClasspath()
.withArguments(
":$fixtureName:assembleMinApi24DemoDebug",
":$fixtureName:assembleMinApi24DemoDebugAndroidTest",
":$fixtureName:printYml",
"--stacktrace",
).build()

assertThat(result.output).contains("BUILD SUCCESSFUL")
assertThat(result.output).containsMatch(
"""app: \S*/android-project-multiple-flavor-dimensions/build/outputs/apk/minApi24Demo/debug/android-project-multiple-flavor-dimensions-minApi24-demo-debug\.apk""",
)
assertThat(result.output).containsMatch(
"""test: \S*/android-project-multiple-flavor-dimensions/build/outputs/apk/androidTest/minApi24Demo/debug/android-project-multiple-flavor-dimensions-minApi24-demo-debug-androidTest\.apk""",
)
assertThat(result.output).doesNotContain("/minApi24/demo/debug/")
assertThat(result.output).doesNotContain("-minApi24demo-debug")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,88 @@ class FulladlePluginIntegrationTest {
)
}

@Test
fun fulladleWithMultipleFlavorDimensions() {
val appFixture = "android-project"
val flavourProject = "android-project-multiple-flavor-dimensions"
val flavourLibrary = "android-library-project-multiple-flavor-dimensions"
testProjectRoot.newFile("settings.gradle").writeText(
"""
include '$appFixture'
include '$flavourProject'
include '$flavourLibrary'

dependencyResolutionManagement {
repositories {
mavenCentral()
google()
}
}
""".trimIndent(),
)
testProjectRoot.setupFixture(appFixture)
testProjectRoot.setupFixture(flavourProject)
testProjectRoot.setupFixture(flavourLibrary)

writeBuildGradle(
"""
buildscript {
repositories {
google()
}

dependencies {
classpath '$agpDependency'
}
}

plugins {
id "com.osacky.fulladle"
}

fladle {
serviceAccountCredentials = project.layout.projectDirectory.file("android-project/flank-gradle-5cf02dc90531.json")
}
""".trimIndent(),
)

File(testProjectRoot.root, "$flavourProject/build.gradle").appendText(
"""

fulladleModuleConfig {
variant = "minApi24DemoDebug"
}
""".trimIndent(),
)
File(testProjectRoot.root, "$flavourLibrary/build.gradle").appendText(
"""

fulladleModuleConfig {
variant = "minApi24DemoDebug"
}
""".trimIndent(),
)

val result =
testProjectRoot
.gradleRunner()
.withArguments(":printYml")
.build()

assertThat(result.output).contains("SUCCESS")
assertThat(result.output).containsMatch(
"""app: \S*/android-project-multiple-flavor-dimensions/build/outputs/apk/minApi24Demo/debug/android-project-multiple-flavor-dimensions-minApi24-demo-debug\.apk""",
)
assertThat(result.output).containsMatch(
"""test: \S*/android-project-multiple-flavor-dimensions/build/outputs/apk/androidTest/minApi24Demo/debug/android-project-multiple-flavor-dimensions-minApi24-demo-debug-androidTest\.apk""",
)
assertThat(result.output).containsMatch(
"""test: \S*/android-library-project-multiple-flavor-dimensions/build/outputs/apk/androidTest/minApi24Demo/debug/android-library-project-multiple-flavor-dimensions-minApi24-demo-debug-androidTest\.apk""",
)
assertThat(result.output).doesNotContain("/minApi24/demo/debug/")
assertThat(result.output).doesNotContain("-minApi24demo-debug")
}

@Test
fun fulladleWithDefaultFlavor() {
val appFixture = "android-project"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
plugins {
id 'com.android.library'
}

android {
compileSdk 33
namespace = "com.osacky.flank.gradle.sample"
defaultConfig {
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
testOptions {
execution 'ANDROIDX_TEST_ORCHESTRATOR'
}
flavorDimensions "api", "mode"

productFlavors {
minApi24 {
dimension "api"
}
demo {
dimension "mode"
}
}
}

dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation("androidx.navigation:navigation-fragment-ktx:2.3.0")
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test:rules:1.5.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.osacky.flank.gradle.sample;


import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import androidx.test.rule.ActivityTestRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.action.ViewActions.typeText;
import java.lang.RuntimeException;

@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {

@Rule
private final ActivityTestRule testRule = new ActivityTestRule(MainActivity.class);

@Test
public void seeView() {
onView(withId(R.id.text_view_hello)).check(matches(isDisplayed()));
}

@Test
public void runAndFail() {
throw new RuntimeException("Test failed");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android">

<application
android:label="@string/app_name"
>
<activity android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>

</manifest>
Loading