Skip to content

Commit 6eb0419

Browse files
author
Marcel Schnelle
authored
Fix multi-dimension projects that try to access non-existing filters (#113)
Fixes #110
1 parent 35dbbf0 commit 6eb0419

File tree

4 files changed

+187
-17
lines changed

4 files changed

+187
-17
lines changed

android-junit5-tests/src/test/groovy/de/mannodermaus/gradle/plugins/junit5/DslGroovyTests.groovy

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,74 @@ class DslGroovyTests {
113113
containsOnly("some-tag", "paid-tag", "release-tag")
114114
assertThat(paidReleaseTask.testFramework.options.excludeTags).containsOnly("other-tag")
115115
}
116+
117+
@org.junit.jupiter.api.Test
118+
@DisplayName("complex example with multiple flavor dimensions & build types")
119+
void complexExampleWithMultipleFlavorDimensionsAndBuildTypes() {
120+
def project = factory.newProject(testRoot)
121+
.asAndroidApplication()
122+
.build()
123+
124+
project.android {
125+
flavorDimensions "brand", "environment", "payment"
126+
productFlavors {
127+
brandA {
128+
dimension "brand"
129+
}
130+
brandB {
131+
dimension "brand"
132+
}
133+
134+
development {
135+
dimension "environment"
136+
}
137+
production {
138+
dimension "environment"
139+
}
140+
141+
free {
142+
dimension "payment"
143+
}
144+
paid {
145+
dimension "payment"
146+
}
147+
}
148+
149+
buildTypes {
150+
ci {
151+
initWith debug
152+
}
153+
}
154+
155+
testOptions.junitPlatform {
156+
filters {
157+
includeTags "global-tag"
158+
}
159+
160+
brandAFilters {
161+
includeTags "brandA-tag"
162+
includeTags "some-other-tag"
163+
}
164+
165+
developmentFilters {
166+
includeTags "development-tag"
167+
}
168+
169+
paidFilters {
170+
includeTags "paid-tag"
171+
excludeTags "some-other-tag"
172+
}
173+
}
174+
}
175+
176+
project.evaluate()
177+
178+
def brandADevelopmentPaidDebugTask = project.tasks
179+
.getByName("testBrandADevelopmentPaidDebugUnitTest") as Test
180+
181+
assertThat(brandADevelopmentPaidDebugTask.testFramework.options.includeTags).
182+
containsOnly("global-tag", "brandA-tag", "development-tag", "paid-tag")
183+
assertThat(brandADevelopmentPaidDebugTask.testFramework.options.excludeTags).
184+
containsOnly("some-other-tag")
185+
}
116186
}

android-junit5-tests/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/PluginSpec.kt

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import org.gradle.api.ProjectConfigurationException
1919
import org.gradle.api.Task
2020
import org.gradle.api.internal.plugins.PluginApplicationException
2121
import org.gradle.api.tasks.testing.Test
22-
import org.gradle.testkit.runner.GradleRunner
2322
import org.jetbrains.spek.api.Spek
2423
import org.jetbrains.spek.api.dsl.context
2524
import org.jetbrains.spek.api.dsl.describe
@@ -575,6 +574,76 @@ class PluginSpec : Spek({
575574
}
576575
}
577576

577+
on("using custom build types & multiple flavor dimensions") {
578+
project.android.apply {
579+
flavorDimensions("brand", "environment", "payment")
580+
productFlavors.apply {
581+
create("brandA").dimension = "brand"
582+
create("brandB").dimension = "brand"
583+
584+
create("development").dimension = "environment"
585+
create("production").dimension = "environment"
586+
587+
create("free").dimension = "payment"
588+
create("paid").dimension = "payment"
589+
}
590+
buildTypes.apply {
591+
create("ci").initWith(findByName("debug"))
592+
}
593+
}
594+
595+
project.evaluate()
596+
597+
listOf(
598+
"filters",
599+
600+
"debugFilters",
601+
"releaseFilters",
602+
"ciFilters",
603+
604+
"brandAFilters",
605+
"brandBFilters",
606+
607+
"developmentFilters",
608+
"productionFilters",
609+
610+
"freeFilters",
611+
"paidFilters",
612+
613+
"brandADevelopmentPaidDebugFilters",
614+
"brandADevelopmentPaidReleaseFilters",
615+
"brandADevelopmentPaidCiFilters",
616+
"brandADevelopmentFreeDebugFilters",
617+
"brandADevelopmentFreeReleaseFilters",
618+
"brandADevelopmentFreeCiFilters",
619+
"brandAProductionPaidDebugFilters",
620+
"brandAProductionPaidReleaseFilters",
621+
"brandAProductionPaidCiFilters",
622+
"brandAProductionFreeDebugFilters",
623+
"brandAProductionFreeReleaseFilters",
624+
"brandAProductionFreeCiFilters",
625+
626+
"brandBDevelopmentPaidDebugFilters",
627+
"brandBDevelopmentPaidReleaseFilters",
628+
"brandBDevelopmentPaidCiFilters",
629+
"brandBDevelopmentFreeDebugFilters",
630+
"brandBDevelopmentFreeReleaseFilters",
631+
"brandBDevelopmentFreeCiFilters",
632+
"brandBProductionPaidDebugFilters",
633+
"brandBProductionPaidReleaseFilters",
634+
"brandBProductionPaidCiFilters",
635+
"brandBProductionFreeDebugFilters",
636+
"brandBProductionFreeReleaseFilters",
637+
"brandBProductionFreeCiFilters"
638+
).forEach { name ->
639+
it("creates an extension named '$name'") {
640+
val ju5 = project.android.testOptions.junitPlatform
641+
val extension = ju5.extensionByName<FiltersExtension>(name)
642+
assertThat(extension).isNotNull()
643+
}
644+
}
645+
}
646+
578647
on("using flavor-specific filters") {
579648
project.android.flavorDimensions("tier")
580649
project.android.productFlavors.apply {

android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/Configuration.kt

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,33 @@ internal class JUnit5TaskConfig(
9494
// 2) Build-type-specific (e.g. "debug")
9595
// 3) Flavor-specific (e.g. "free")
9696
// 4) Variant-specific (e.g. "freeDebug")
97-
private fun collect(collectorFunction: (FiltersExtension) -> IncludeExcludeContainer) =
98-
collectorFunction(extension.filters) +
99-
collectorFunction(extension.findFilters(variant.buildType.name)) +
100-
collectorFunction(extension.findFilters(variant.flavorName)) +
101-
collectorFunction(extension.findFilters(variant.name))
102-
103-
val combinedIncludePatterns = this.collect { it.patterns }.include.toTypedArray()
104-
val combinedExcludePatterns = this.collect { it.patterns }.exclude.toTypedArray()
105-
val combinedIncludeTags = this.collect { it.tags }.include.toTypedArray()
106-
val combinedExcludeTags = this.collect { it.tags }.exclude.toTypedArray()
107-
val combinedIncludeEngines = this.collect { it.engines }.include.toTypedArray()
108-
val combinedExcludeEngines = this.collect { it.engines }.exclude.toTypedArray()
97+
private fun collect(
98+
func: FiltersExtension.() -> IncludeExcludeContainer): IncludeExcludeContainer {
99+
// 1)
100+
val layer1 = filtersOf(null, func)
101+
// 2)
102+
val layer2 = layer1 + filtersOf(variant.buildType.name, func)
103+
// 3)
104+
val layer3 = variant.productFlavors
105+
.map { filtersOf(it.name, func) }
106+
.fold(layer2) { a, b -> a + b }
107+
// 4)
108+
return layer3 + filtersOf(variant.name, func)
109+
}
110+
111+
private inline fun filtersOf(
112+
qualifier: String?,
113+
func: FiltersExtension.() -> IncludeExcludeContainer) =
114+
if (qualifier == null) {
115+
extension.filters.func()
116+
} else {
117+
extension.findFilters(qualifier).func()
118+
}
119+
120+
val combinedIncludePatterns = this.collect { patterns }.include.toTypedArray()
121+
val combinedExcludePatterns = this.collect { patterns }.exclude.toTypedArray()
122+
val combinedIncludeTags = this.collect { tags }.include.toTypedArray()
123+
val combinedExcludeTags = this.collect { tags }.exclude.toTypedArray()
124+
val combinedIncludeEngines = this.collect { engines }.include.toTypedArray()
125+
val combinedExcludeEngines = this.collect { engines }.exclude.toTypedArray()
109126
}

android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/Dsl.kt

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,30 @@ internal fun attachDsl(project: Project, projectConfig: ProjectConfig) {
2727
// as well as composed variants (e.g. "freeDebug" or "paidRelease")
2828
// and product flavors (e.g. "free" or "paid")
2929
project.android.buildTypes.all { buildType ->
30+
// "debugFilters"
31+
// "releaseFilters"
3032
ju5.attachFiltersDsl(qualifier = buildType.name)
3133
}
3234

35+
// Attach DSL objects for all permutations of variants available.
36+
// As an example, assume the incoming `variant` to be:
37+
// Name: "brandADevelopmentDebug"
38+
// Dimension "brand": "brandA"
39+
// Dimension "environment": "development"
40+
// Build Type Name: "debug"
41+
//
42+
// The following DSL objects have to be generated from this:
43+
// 1) brandADevelopmentDebugFilters
44+
// 2) brandAFilters
45+
// 3) developmentFilters
3346
projectConfig.unitTestVariants.all { variant ->
47+
// 1) Fully-specialized name ("brandADevelopmentDebugFilters")
3448
ju5.attachFiltersDsl(qualifier = variant.name)
35-
ju5.attachFiltersDsl(qualifier = variant.buildType.name)
36-
}
3749

38-
project.android.productFlavors.all { flavor ->
39-
ju5.attachFiltersDsl(qualifier = flavor.name)
50+
variant.productFlavors.forEach { flavor ->
51+
// 2) & 3) Single flavors ("brandAFilters" & "developmentFilters")
52+
ju5.attachFiltersDsl(qualifier = flavor.name)
53+
}
4054
}
4155
}
4256
}

0 commit comments

Comments
 (0)