From fe124e1beebd00482586f62d45d8f58775a6f376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Janek=20G=C3=B3ral?= Date: Fri, 14 May 2021 11:55:48 +0200 Subject: [PATCH] Add public API of domain layer without business logic. --- corellium/domain/build.gradle.kts | 29 +++++++ .../domain/RunTestAndroidCorellium.kt | 79 +++++++++++++++++++ .../flank/corellium/domain/util/Transform.kt | 23 ++++++ settings.gradle.kts | 1 + 4 files changed, 132 insertions(+) create mode 100644 corellium/domain/build.gradle.kts create mode 100644 corellium/domain/src/main/kotlin/flank/corellium/domain/RunTestAndroidCorellium.kt create mode 100644 corellium/domain/src/main/kotlin/flank/corellium/domain/util/Transform.kt diff --git a/corellium/domain/build.gradle.kts b/corellium/domain/build.gradle.kts new file mode 100644 index 0000000000..68f212feb5 --- /dev/null +++ b/corellium/domain/build.gradle.kts @@ -0,0 +1,29 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + kotlin(Plugins.Kotlin.PLUGIN_JVM) + kotlin(Plugins.Kotlin.PLUGIN_SERIALIZATION) version Versions.KOTLIN +} + +repositories { + jcenter() + mavenCentral() + maven(url = "https://kotlin.bintray.com/kotlinx") +} + +tasks.withType { kotlinOptions.jvmTarget = "1.8" } + +dependencies { + implementation(Dependencies.KOTLIN_COROUTINES_CORE) + implementation(project(":corellium:api")) + implementation(project(":corellium:shard:calculate")) + implementation(project(":corellium:log")) + + testImplementation(Dependencies.JUNIT) +} + +tasks.test { + maxHeapSize = "3072m" + minHeapSize = "512m" + dependsOn(":resolveArtifacts") +} diff --git a/corellium/domain/src/main/kotlin/flank/corellium/domain/RunTestAndroidCorellium.kt b/corellium/domain/src/main/kotlin/flank/corellium/domain/RunTestAndroidCorellium.kt new file mode 100644 index 0000000000..139ab4ec2e --- /dev/null +++ b/corellium/domain/src/main/kotlin/flank/corellium/domain/RunTestAndroidCorellium.kt @@ -0,0 +1,79 @@ +package flank.corellium.domain + +import flank.corellium.api.Authorization +import flank.corellium.api.CorelliumApi +import flank.corellium.domain.RunTestAndroidCorellium.Context +import flank.corellium.domain.RunTestAndroidCorellium.State +import flank.corellium.domain.util.CreateTransformation +import flank.corellium.domain.util.execute +import flank.corellium.log.Instrument +import flank.corellium.shard.Shard +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.runBlocking +import java.util.Date + +object RunTestAndroidCorellium { + + /** + * The context of android test execution on corellium. + * Is providing all necessary data and operations for [Context.invoke]. + */ + interface Context { + val api: CorelliumApi + val config: Config + } + + /** + * The user configuration for invocation. + */ + data class Config( + val credentials: Authorization.Credentials, + val apks: List, + val maxShardsCount: Int, + val outputDir: String = "results/corellium/android/" + Date(), + ) + + sealed class Apk { + abstract val path: String + + data class App( + override val path: String, + val tests: List, + ) : Apk() + + data class Test( + override val path: String + ) : Apk() + } + + /** + * The State structure is holding all necessary data collected during the execution process. + * For convenience the properties are sorted in order equal to its initialization. + * + * @param testCases key - path to the test apk, value - list of test method names. + * @param shards each item is representing list of apps to run on another device instance. + * @param ids the ids of corellium device instances. + * @param packageNames key - path to the test apk, value - package name. + * @param testRunners key - path to the test apk, value - fully qualified test runner name. + */ + internal data class State( + val testCases: Map> = emptyMap(), + val shards: List> = emptyList(), + val ids: List = emptyList(), + val packageNames: Map = emptyMap(), + val testRunners: Map = emptyMap(), + val testResult: List> = emptyList(), + ) + + /** + * The reference to the step factory function. + * Invoke it to generate new execution step. + */ + internal val step = CreateTransformation() +} + +operator fun Context.invoke(): Unit = runBlocking { + State() execute flowOf( + // TODO steps will be added in next PR + ) +} diff --git a/corellium/domain/src/main/kotlin/flank/corellium/domain/util/Transform.kt b/corellium/domain/src/main/kotlin/flank/corellium/domain/util/Transform.kt new file mode 100644 index 0000000000..e24822ffb3 --- /dev/null +++ b/corellium/domain/src/main/kotlin/flank/corellium/domain/util/Transform.kt @@ -0,0 +1,23 @@ +package flank.corellium.domain.util + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.fold + +/** + * Execute flow of suspendable transformations on a given value. + * + * @receiver Value to apply transformations on it. + * @return Result of transformations. + */ +internal suspend infix fun S.execute(operations: Flow>): S = + operations.fold(this) { value, transform -> transform(value) } + +/** + * Simple parameterized factory for generating [Transform] instances. + */ +internal class CreateTransformation : (Transform) -> Transform by { it } + +/** + * Type-alias for suspendable transforming operation + */ +private typealias Transform = suspend S.() -> S diff --git a/settings.gradle.kts b/settings.gradle.kts index 277134d9bc..17586aa6ee 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,6 +21,7 @@ include( ":corellium:shard:dump", ":corellium:adapter", ":corellium:junit", + ":corellium:domain", ) plugins {