Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Several minor corellium changes - part 3. #1943

Merged
merged 1 commit into from
May 18, 2021
Merged
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 @@ -3,24 +3,28 @@ package flank.corellium.cli
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import com.fasterxml.jackson.annotation.JsonProperty
import flank.corellium.cli.RunTestCorelliumAndroidCommand.Config
import flank.corellium.cli.util.ConfigMap
import flank.corellium.cli.util.emptyConfigMap
import flank.corellium.cli.util.loadYaml
import flank.corellium.cli.util.merge
import flank.corellium.corelliumApi
import flank.corellium.domain.RunTestAndroidCorellium
import flank.corellium.domain.RunTestCorelliumAndroid
import flank.corellium.domain.RunTestCorelliumAndroid.Args
import flank.corellium.domain.invoke
import picocli.CommandLine

class RunTestCorelliumAndroidCommand :
Runnable,
RunTestAndroidCorellium.Context {
RunTestCorelliumAndroid.Context {

@JsonIgnoreProperties(ignoreUnknown = true)
data class Config @JsonIgnore constructor(
@JsonIgnore
override val data: MutableMap<String, Any?>
) : ConfigMap {
constructor() : this(emptyConfigMap())

@set:CommandLine.Option(
names = ["-a", "--auth"],
description = ["YAML authorization file path"]
Expand All @@ -43,14 +47,14 @@ class RunTestCorelliumAndroidCommand :
)
fun addApks(map: Map<String, String>) {
apks = (apks ?: emptyList()) + map.map { (app, tests) ->
RunTestAndroidCorellium.Apk.App(
Args.Apk.App(
path = app,
tests = tests.split(",").map(RunTestAndroidCorellium.Apk::Test)
tests = tests.split(",").map(Args.Apk::Test)
)
}
}

var apks: List<RunTestAndroidCorellium.Apk.App>? by data
var apks: List<Args.Apk.App>? by data

@set:CommandLine.Option(
names = ["--max-test-shards"],
Expand All @@ -66,7 +70,14 @@ class RunTestCorelliumAndroidCommand :
@set:JsonProperty("local-result-dir")
var localResultsDir: String? by data

constructor() : this(emptyConfigMap())
@set:CommandLine.Option(
names = ["--obfuscate"],
description = [
"Replacing internal test names with unique identifiers when using --dump-shards option " +
"to avoid exposing internal details"
]
)
var obfuscate: Boolean? by data
}

@CommandLine.Mixin
Expand All @@ -87,20 +98,22 @@ class RunTestCorelliumAndroidCommand :
override fun run() = invoke()
}

private fun defaultConfig() = RunTestCorelliumAndroidCommand.Config().apply {
auth = "auth.yml"
private fun defaultConfig() = Config().apply {
project = "Default Project"
auth = "auth.yml"
apks = emptyList()
maxTestShards = 3
localResultsDir = ""
localResultsDir = null
obfuscate = false
}

private fun RunTestCorelliumAndroidCommand.yamlConfig(): RunTestCorelliumAndroidCommand.Config =
yamlConfigPath?.let(::loadYaml) ?: RunTestCorelliumAndroidCommand.Config()
private fun RunTestCorelliumAndroidCommand.yamlConfig(): Config =
yamlConfigPath?.let(::loadYaml) ?: Config()

private fun RunTestCorelliumAndroidCommand.createArgs() = RunTestAndroidCorellium.Args(
private fun RunTestCorelliumAndroidCommand.createArgs() = Args(
credentials = loadYaml(config.auth!!),
apks = config.apks!!,
outputDir = config.localResultsDir!!,
maxShardsCount = config.maxTestShards!!,
credentials = loadYaml(config.auth!!)
outputDir = config.localResultsDir ?: Args.DefaultOutputDir.new,
obfuscateDumpShards = config.obfuscate!!,
)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package flank.corellium.cli

import flank.corellium.api.Authorization
import flank.corellium.domain.RunTestAndroidCorellium
import flank.corellium.domain.RunTestCorelliumAndroid.Args
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Test
Expand All @@ -17,22 +17,23 @@ class RunTestCorelliumAndroidCommandTest {
auth = "test_auth.yml"
project = "test project"
apks = listOf(
RunTestAndroidCorellium.Apk.App(
Args.Apk.App(
"app1.apk",
tests = listOf(
RunTestAndroidCorellium.Apk.Test("app1-test1.apk"),
Args.Apk.Test("app1-test1.apk"),
)
),
RunTestAndroidCorellium.Apk.App(
Args.Apk.App(
"app2.apk",
tests = listOf(
RunTestAndroidCorellium.Apk.Test("app2-test1.apk"),
RunTestAndroidCorellium.Apk.Test("app2-test2.apk"),
Args.Apk.Test("app2-test1.apk"),
Args.Apk.Test("app2-test2.apk"),
)
),
)
maxTestShards = Int.MAX_VALUE
localResultsDir = "test_result_dir"
obfuscate = true
}

/**
Expand All @@ -50,11 +51,12 @@ class RunTestCorelliumAndroidCommandTest {

val cliArgs = expectedConfig.run {
arrayOf(
"--auth=$auth",
"--project=$project",
"--auth=$auth",
"--apks=app1.apk=app1-test1.apk;app2.apk=app2-test1.apk,app2-test2.apk",
"--max-test-shards=$maxTestShards",
"--local-result-dir=$localResultsDir"
"--local-result-dir=$localResultsDir",
"--obfuscate=$obfuscate",
)
}

Expand All @@ -72,7 +74,7 @@ apks:
- path: "app2-test2.apk"
max-test-shards: $maxTestShards
local-result-dir: $localResultsDir
obfuscate: $obfuscate
""".trimIndent()
}

Expand Down Expand Up @@ -129,11 +131,12 @@ local-result-dir: $localResultsDir
)

val expected = testConfig.run {
RunTestAndroidCorellium.Args(
Args(
credentials = expectedCredentials,
apks = apks!!,
maxShardsCount = maxTestShards!!,
outputDir = localResultsDir!!
outputDir = localResultsDir!!,
obfuscateDumpShards = obfuscate!!
)
}

Expand Down
4 changes: 4 additions & 0 deletions corellium/domain/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ dependencies {
implementation(Dependencies.KOTLIN_COROUTINES_CORE)
implementation(project(":corellium:api"))
implementation(project(":corellium:shard:calculate"))
implementation(project(":corellium:shard:obfuscate"))
implementation(project(":corellium:shard:dump"))
implementation(project(":corellium:log"))
implementation(project(":corellium:junit"))

testImplementation(Dependencies.JUNIT)
testImplementation(project(":corellium:adapter"))
}

tasks.test {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ 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.RunTestCorelliumAndroid.Context
import flank.corellium.domain.RunTestCorelliumAndroid.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.lang.System.currentTimeMillis
import java.text.SimpleDateFormat

object RunTestAndroidCorellium {
object RunTestCorelliumAndroid {

/**
* The context of android test execution on corellium.
Expand All @@ -29,20 +31,31 @@ object RunTestAndroidCorellium {
val credentials: Authorization.Credentials,
val apks: List<Apk.App>,
val maxShardsCount: Int,
val outputDir: String,
)
val obfuscateDumpShards: Boolean = false,
val outputDir: String = DefaultOutputDir.new,
) {
object DefaultOutputDir {
private const val PATH = "results/corellium/android/"
private val date = SimpleDateFormat("yyyy-MM-dd_HH-mm-ss-SSS")
val new get() = PATH + date.format(currentTimeMillis())
}

sealed class Apk {
abstract val path: String
/**
* Abstraction for app and test apk files.
* @property path Absolut or relative path to apk file.
*/
sealed class Apk {
abstract val path: String

data class App(
override val path: String,
val tests: List<Test>,
) : Apk()
data class App(
override val path: String,
val tests: List<Test>
) : Apk()

data class Test(
override val path: String
) : Apk()
data class Test(
override val path: String
) : Apk()
}
}

/**
Expand All @@ -65,7 +78,7 @@ object RunTestAndroidCorellium {
)

/**
* The reference to the step factory function.
* The reference to the step factory.
* Invoke it to generate new execution step.
*/
internal val step = CreateTransformation<State>()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package flank.corellium.domain

import flank.corellium.corelliumApi

object RunTestAndroidCorelliumExample : RunTestCorelliumAndroid.Context {
override val api = corelliumApi("Default Project")
override val args = RunTestCorelliumAndroid.Args(
credentials = loadedCredentials,
apks = fewTestArtifactsApks(APK_PATH_MAIN),
maxShardsCount = 3
)
}

fun main() = RunTestAndroidCorelliumExample()
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package flank.corellium.domain

import flank.corellium.api.Apk
import flank.corellium.api.CorelliumApi
import flank.corellium.domain.RunTestCorelliumAndroid.Args
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.map
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Test
import java.io.File

class RunTestAndroidCorelliumTestMockApiAndroid : RunTestCorelliumAndroid.Context {

private val expectedShardsCount = 4

override val args = Args(
credentials = stubCredentials,
apks = listOf(
Args.Apk.App(
path = "app1",
tests = listOf(
Args.Apk.Test("app1/test1"),
Args.Apk.Test("app1/test2"),
Args.Apk.Test("app1/test3"),
)
),
Args.Apk.App(
path = "app2",
tests = listOf(
Args.Apk.Test("app2/test1"),
Args.Apk.Test("app2/test2")
)
),
Args.Apk.App(
path = "app3",
tests = listOf(
Args.Apk.Test("app3/test1")
)
),
),
maxShardsCount = expectedShardsCount
)

override val api = CorelliumApi(
authorize = { credentials ->
println(credentials)
assertEquals(args.credentials, credentials)
completeJob
},
parseTestCases = { path ->
println(path)
(1..path.last().toString().toInt()).map {
path.replace("/", ".") + ".Test#test$it"
}
},
invokeAndroidDevices = { (amount) ->
assertEquals(expectedShardsCount, amount)
(1..amount).asFlow().map(Int::toString)
},
installAndroidApps = { list ->
println(list)
assertEquals(expectedShardsCount, list.size)
completeJob
},
parsePackageName = { path ->
println(path)
path
},
parseTestApkInfo = { path ->
println(path)
Apk.Info(
packageName = path,
testRunner = path
)
},
executeTest = { (instances) ->
println(instances)
assertEquals(expectedShardsCount, instances.size)
emptyList()
},
)

@Test
fun test(): Unit = invoke()

@After
fun cleanUp() {
File(args.outputDir).deleteRecursively()
}
}
Loading