Skip to content

Commit

Permalink
Add validation
Browse files Browse the repository at this point in the history
  • Loading branch information
pawelpasterz committed Sep 29, 2020
1 parent 4cfe399 commit a3ef5d3
Show file tree
Hide file tree
Showing 9 changed files with 241 additions and 189 deletions.
13 changes: 13 additions & 0 deletions buildSrc/src/main/java/com/osacky/flank/gradle/FladleConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@ interface FladleConfig {
@get:Optional
val serviceAccountCredentials: RegularFileProperty

/**
* debugApk and instrumentationApk are [Property<String>] and not [RegularFileProperty] because we support wildcard characters.
*/
@get:Input
@get:Optional
val debugApk: Property<String>
@get:Input
@get:Optional
val instrumentationApk: Property<String>

@get:Input
val sanityRobo: Property<Boolean>

@get:Input
val useOrchestrator: Property<Boolean>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ data class FladleConfigImpl(
internal val name: String,
override val projectId: Property<String>,
override val serviceAccountCredentials: RegularFileProperty,
override val debugApk: Property<String>,
override val instrumentationApk: Property<String>,
override val sanityRobo: Property<Boolean>,
override val useOrchestrator: Property<Boolean>,
override val autoGoogleLogin: Property<Boolean>,
override val devices: ListProperty<Map<String, String>>,
Expand Down Expand Up @@ -45,4 +48,12 @@ data class FladleConfigImpl(
override val outputStyle: Property<String>,
override val legacyJunitResult: Property<Boolean>,
override val fullJunitResult: Property<Boolean>
) : FladleConfig
) : FladleConfig {
fun sanityRoboRun() {
sanityRobo.set(true)
additionalTestApks.empty()
instrumentationApk.set("")
roboDirectives.empty()
roboScript.set("")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class FladlePluginDelegate {
// Must be done afterEvaluate otherwise extension values will not be set.
project.dependencies.add(FLADLE_CONFIG, "${base.flankCoordinates.get()}:${base.flankVersion.get()}")

checkIfSanityAndValidateConfigs(base)
base.configs.forEach(::checkIfSanityAndValidateConfigs)

// Only use automatic apk path detection for 'com.android.application' projects.
project.pluginManager.withPlugin("com.android.application") {
if (!base.debugApk.isPresent || !base.instrumentationApk.isPresent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,96 +20,58 @@ open class FlankGradleExtension @Inject constructor(objects: ObjectFactory) : Fl
val flankCoordinates: Property<String> = objects.property(String::class.java).convention("com.github.flank:flank")

@get:Input
val sanityRobo: Property<Boolean> = objects.property<Boolean>().convention(false)
val flankVersion: Property<String> = objects.property(String::class.java).convention("20.09.3")

// Variant to use for configuring output APK.
@get:Input
val flankVersion: Property<String> = objects.property(String::class.java).convention("20.09.3")
@get:Optional
val variant: Property<String> = objects.property()

// Project id is automatically discovered by default. Use this to override the project id.
override val projectId: Property<String> = objects.property()
override val serviceAccountCredentials: RegularFileProperty = objects.fileProperty()
override val useOrchestrator: Property<Boolean> = objects.property<Boolean>().convention(false)
override val autoGoogleLogin: Property<Boolean> = objects.property<Boolean>().convention(false)
override val devices: ListProperty<Map<String, String>> = objects.listProperty<Map<String, String>>().convention(listOf(mapOf("model" to "NexusLowRes", "version" to "28")))
override val sanityRobo: Property<Boolean> = objects.property<Boolean>().convention(false)

// https://cloud.google.com/sdk/gcloud/reference/firebase/test/android/run
override val testTargets: ListProperty<String> = objects.listProperty()

override val testShards: Property<Int> = objects.property()
override val shardTime: Property<Int> = objects.property()
override val repeatTests: Property<Int> = objects.property()

// Shard Android tests by time using historical run data. The amount of shards used is set by `testShards`.
override val smartFlankGcsPath: Property<String> = objects.property()

override val resultsHistoryName: Property<String> = objects.property()

override val flakyTestAttempts: Property<Int> = objects.property<Int>().convention(0)

// Variant to use for configuring output APK.
@get:Input
@get:Optional
val variant: Property<String> = objects.property()

/**
* debugApk and instrumentationApk are [Property<String>] and not [RegularFileProperty] because we support wildcard characters.
*/
@get:Input
@get:Optional
val debugApk: Property<String> = objects.property()
@get:Input
@get:Optional
val instrumentationApk: Property<String> = objects.property()

override val debugApk: Property<String> = objects.property()
override val instrumentationApk: Property<String> = objects.property()
override val directoriesToPull: ListProperty<String> = objects.listProperty()

override val filesToDownload: ListProperty<String> = objects.listProperty()

override val environmentVariables: MapProperty<String, String> = objects.mapProperty()

override val recordVideo: Property<Boolean> = objects.property<Boolean>().convention(true)

override val performanceMetrics: Property<Boolean> = objects.property<Boolean>().convention(true)

override val resultsBucket: Property<String> = objects.property()

override val keepFilePath: Property<Boolean> = objects.property<Boolean>().convention(false)

override val resultsDir: Property<String> = objects.property()

override val additionalTestApks: ListProperty<String> = objects.listProperty()

override val runTimeout: Property<String> = objects.property()

override val ignoreFailedTests: Property<Boolean> = objects.property<Boolean>().convention(false)

override val disableSharding: Property<Boolean> = objects.property<Boolean>().convention(false)

override val smartFlankDisableUpload: Property<Boolean> = objects.property<Boolean>().convention(false)

override val testRunnerClass: Property<String> = objects.property()

override val localResultsDir: Property<String> = objects.property()

override val numUniformShards: Property<Int> = objects.property()

override val clientDetails: MapProperty<String, String> = objects.mapProperty()

override val testTargetsAlwaysRun: ListProperty<String> = objects.listProperty()

override val otherFiles: MapProperty<String, String> = objects.mapProperty()

override val networkProfile: Property<String> = objects.property()

override val roboScript: Property<String> = objects.property()

override val roboDirectives: ListProperty<List<String>> = objects.listProperty()

override val testTimeout: Property<String> = objects.property<String>().convention("15m")

override val outputStyle: Property<String> = objects.property<String>().convention("single")

override val legacyJunitResult: Property<Boolean> = objects.property<Boolean>().convention(false)

override val fullJunitResult: Property<Boolean> = objects.property<Boolean>().convention(false)

@Internal
Expand All @@ -118,6 +80,9 @@ open class FlankGradleExtension @Inject constructor(objects: ObjectFactory) : Fl
name = it,
projectId = objects.property<String>().convention(projectId),
serviceAccountCredentials = objects.fileProperty().convention(serviceAccountCredentials),
debugApk = objects.property<String>().convention(debugApk),
instrumentationApk = objects.property<String>().convention(instrumentationApk),
sanityRobo = objects.property<Boolean>().convention(false),
useOrchestrator = objects.property<Boolean>().convention(useOrchestrator),
autoGoogleLogin = objects.property<Boolean>().convention(autoGoogleLogin),
devices = objects.listProperty<Map<String, String>>().convention(devices),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.osacky.flank.gradle

import org.gradle.api.GradleException
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property

@Throws(GradleException::class)
fun checkIfSanityAndValidateConfigs(config: FladleConfig) = when (config) {
is FlankGradleExtension -> config.checkAndValidateExtension()
is FladleConfigImpl -> config.checkAndValidateConfig()
else -> throw GradleException("Unable to check for sanity, check config type")
}

private fun FlankGradleExtension.checkAndValidateExtension() {
if (sanityRobo.getOrElse(false)) when {
instrumentationApk.isNotPresentOrBlank -> throwBaseConfigError("instrumentationApk")
additionalTestApks.isNotPresentOrEmpty -> throwBaseConfigError("additionalTestApks")
roboDirectives.isNotPresentOrEmpty -> throwBaseConfigError("roboDirectives")
roboScript.isNotPresentOrBlank -> throwBaseConfigError("roboScript")
}
}

private fun FladleConfigImpl.checkAndValidateConfig() {
if (sanityRobo.getOrElse(false)) when {
roboDirectives.isNotPresentOrEmpty -> throwAdditionalConfigError("roboDirectives", name)
roboScript.isNotPresentOrBlank -> throwAdditionalConfigError("roboScript", name)
instrumentationApk.isNotPresentOrBlank -> throwAdditionalConfigError("instrumentationApk", name)
additionalTestApks.isNotPresentOrEmpty -> throwAdditionalConfigError("additionalTestApks", name)
}
}

private fun throwBaseConfigError(option: String): Nothing =
throw GradleException("Incorrect [base] configuration. [$option] can't be used together with sanityRobo.")

private fun throwAdditionalConfigError(option: String, name: String): Nothing =
throw GradleException(
"Incorrect [$name] configuration. [$option] can't be used together with sanityRobo. " +
"If you want to launch robo test run without robo script place only sanityRoboRun() into [$name] configuration"
)

private val Property<String>.isNotPresentOrBlank
get() = orNull.isNullOrBlank().not()

private val <T> ListProperty<T>.isNotPresentOrEmpty
get() = getOrElse(emptyList()).isEmpty().not()
16 changes: 8 additions & 8 deletions buildSrc/src/main/java/com/osacky/flank/gradle/YamlWriter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,26 @@ internal class YamlWriter {
check(base.serviceAccountCredentials.isPresent) { "ServiceAccountCredentials in fladle extension not set. https://github.com/runningcode/fladle#serviceaccountcredentials" }
}
check(base.debugApk.isPresent) { "debugApk must be specified" }
if (base.sanityRobo.get() == false) {
check(base.sanityRobo.get() == true || (base.instrumentationApk.isPresent xor !base.roboScript.orNull.isNullOrBlank())) {
if (config.sanityRobo.get() == false) {
check(config.instrumentationApk.isPresent xor !config.roboScript.orNull.isNullOrBlank()) {
"""
Either instrumentationApk file or roboScript file must be specified but not both.
instrumentationApk=${base.instrumentationApk.orNull}
roboScript=${base.roboScript.orNull}
instrumentationApk=${config.instrumentationApk.orNull}
roboScript=${config.roboScript.orNull}
""".trimIndent()
}
}

val shouldPrintTestAndRobo = base.sanityRobo.get().not()
val shouldPrintTestAndRobo = config.sanityRobo.get().not()
val additionalProperties = writeAdditionalProperties(config, shouldPrintTestAndRobo)
val flankProperties = writeFlankProperties(config, shouldPrintTestAndRobo)

return buildString {
appendln("gcloud:")
appendln(" app: ${base.debugApk.get()}")
appendln(" app: ${config.debugApk.get()}")
// We don't want to print instrumentation apks if sanityRobo == true
if (shouldPrintTestAndRobo && base.instrumentationApk.isPresent) {
appendln(" test: ${base.instrumentationApk.get()}")
if (shouldPrintTestAndRobo && config.instrumentationApk.isPresent) {
appendln(" test: ${config.instrumentationApk.get()}")
}
if (config.devices.isPresentAndNotEmpty) appendln(createDeviceString(config.devices.get()))
appendln(additionalProperties)
Expand Down
Loading

0 comments on commit a3ef5d3

Please sign in to comment.