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

refactor: Move shards calculation to separated module #1920

Merged
merged 1 commit into from
May 12, 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
99 changes: 5 additions & 94 deletions corellium/shard/README.md
Original file line number Diff line number Diff line change
@@ -1,100 +1,11 @@
# Sharding
# Shards data structures

Depending on the provided test cases duration, the sharding algorithm will:

* Split the test cases from one test apk to run on many devices.
* Group the test cases from many test apks to run on a single device.
* A mix both of the above options.
This module is specifying only a data structures for sharding.

## Diagram

![sharding_class_diagram](http://www.plantuml.com/plantuml/proxy?cache=no&fmt=svg&src=https://raw.githubusercontent.com/Flank/flank/master/docs/corellium/sharding-class.puml)

## Example

### Input

```yaml
bundle:
- app: app1
tests:
- test: app1-test1
cases:
- "class app1.test1.TestClass#test1" // 1s
- app: app2
tests:
- test: app2-test1
cases:
- "class app2.test1.TestClass#test2" // 2s
- "class app2.test1.TestClass#test3" // 3s
- test: app2-test2
cases:
- "class app2.test2.TestClass#test7" // 7s
- "class app2.test2.TestClass#test8" // 8s
- "class app2.test2.TestClass#test9" // 9s
```

### Output

#### Max shards 3

```yaml
shards:
- shard1:
- app: app1
tests:
- test: app1-test1
cases:
- "class app1.test1.TestClass#test1" // 1s
- app: app2
tests:
- test: app2-test2
cases:
- "class app2.test2.TestClass#test9" // 9s
- shard2:
- app: app2
test: app2-test1
cases:
- "class app1.test2.TestClass#test2" // 2s
- app: app2
test: app2-test2
cases:
- "class app2.test2.TestClass#test8" // 8s
- shard3:
- app: app2
test: app2-test1
cases:
- "class app2.test1.TestClass#test3" // 3s
- app: app2
test: app2-test2
cases:
- "class app2.test2.TestClass#test7" // 7s
```
![sharding_class_diagram](http://www.plantuml.com/plantuml/proxy?cache=no&fmt=svg&src=https://raw.githubusercontent.com/Flank/flank/master/docs/corellium/shard-structures.puml)

#### Max shards 2
## Nested modules

```yaml
shards:
- shard1:
- app: app1
tests:
- test: app1-test1
cases:
- "class app1.test1.TestClass#test1" // 1sz
- app: app2
tests:
- test: app2-test1
cases:
- "class app2.test1.TestClass#test2" // 2s
- "class app2.test2.TestClass#test3" // 3s
- test: app2-test2
cases:
- "class app2.test2.TestClass#test9" // 9s
- shard2:
- app: app2
tests:
- test: app2-test2
cases:
- "class app2.test2.TestClass#test7" // 7s
- "class app2.test2.TestClass#test8" // 8s
```
* [:shard:calculate](./calculate)
2 changes: 0 additions & 2 deletions corellium/shard/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
kotlin(Plugins.Kotlin.PLUGIN_JVM)
kotlin(Plugins.Kotlin.PLUGIN_SERIALIZATION) version Versions.KOTLIN
}

repositories {
Expand All @@ -14,7 +13,6 @@ repositories {
tasks.withType<KotlinCompile> { kotlinOptions.jvmTarget = "1.8" }

dependencies {
implementation(Dependencies.KOTLIN_SERIALIZATION)
implementation(Dependencies.KOTLIN_COROUTINES_CORE)

testImplementation(Dependencies.JUNIT)
Expand Down
96 changes: 96 additions & 0 deletions corellium/shard/calculate/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Shards calculation

Depending on the provided test cases duration, the sharding algorithm will:

* Split the test cases from one test apk to run on many devices.
* Group the test cases from many test apks to run on a single device.
* A mix both of the above options.

## Example

### Input

```yaml
bundle:
- app: app1
tests:
- test: app1-test1
cases:
- "class app1.test1.TestClass#test1" // 1s
- app: app2
tests:
- test: app2-test1
cases:
- "class app2.test1.TestClass#test2" // 2s
- "class app2.test1.TestClass#test3" // 3s
- test: app2-test2
cases:
- "class app2.test2.TestClass#test7" // 7s
- "class app2.test2.TestClass#test8" // 8s
- "class app2.test2.TestClass#test9" // 9s
```

### Output

#### Max shards 3

```yaml
shards:
- shard1:
- app: app1
tests:
- test: app1-test1
cases:
- "class app1.test1.TestClass#test1" // 1s
- app: app2
tests:
- test: app2-test2
cases:
- "class app2.test2.TestClass#test9" // 9s
- shard2:
- app: app2
test: app2-test1
cases:
- "class app1.test2.TestClass#test2" // 2s
- app: app2
test: app2-test2
cases:
- "class app2.test2.TestClass#test8" // 8s
- shard3:
- app: app2
test: app2-test1
cases:
- "class app2.test1.TestClass#test3" // 3s
- app: app2
test: app2-test2
cases:
- "class app2.test2.TestClass#test7" // 7s
```

#### Max shards 2

```yaml
shards:
- shard1:
- app: app1
tests:
- test: app1-test1
cases:
- "class app1.test1.TestClass#test1" // 1sz
- app: app2
tests:
- test: app2-test1
cases:
- "class app2.test1.TestClass#test2" // 2s
- "class app2.test2.TestClass#test3" // 3s
- test: app2-test2
cases:
- "class app2.test2.TestClass#test9" // 9s
- shard2:
- app: app2
tests:
- test: app2-test2
cases:
- "class app2.test2.TestClass#test7" // 7s
- "class app2.test2.TestClass#test8" // 8s
```
20 changes: 20 additions & 0 deletions corellium/shard/calculate/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
kotlin(Plugins.Kotlin.PLUGIN_JVM)
}

repositories {
jcenter()
mavenCentral()
maven(url = "https://kotlin.bintray.com/kotlinx")
}

tasks.withType<KotlinCompile> { kotlinOptions.jvmTarget = "1.8" }

dependencies {
implementation(Dependencies.KOTLIN_COROUTINES_CORE)
api(project(":corellium:shard"))

testImplementation(Dependencies.JUNIT)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package flank.corellium.shard

/**
* Distribute the test cases into the [List] of shards where each shard have similar duration.
* @receiver The bunch of test cases grouped by test and app.
* @return [List] of shards where each shard may contains many apps and test cases.
*/
fun Apps.calculateShards(
maxCount: Int
): Shards = this
.mapToInternalChunks()
.groupByDuration(maxCount)
.mapToShards()
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ val apps = listOf(
)
)

class ShardKtTest {
class CalculateShardsTest {

@JTest
fun test2() {
Expand Down
27 changes: 15 additions & 12 deletions corellium/shard/src/main/kotlin/flank/corellium/shard/Shard.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
package flank.corellium.shard

/**
* Distribute the test cases into the [List] of shards where each shard have similar duration.
* @receiver The bunch of test cases grouped by test and app.
* @return [List] of shards where each shard may contains many apps and test cases.
*/
fun List<Shard.App>.calculateShards(
maxCount: Int
): List<List<Shard.App>> = this
.mapToInternalChunks()
.groupByDuration(maxCount)
.mapToShards()

/**
* Namespace for sharding input and output structures.
*/
Expand Down Expand Up @@ -49,3 +37,18 @@ object Shard {

private const val DEFAULT_DURATION = 120L
}

/**
* Collection of apps, tests, and test cases that can be identified as test-shard for running on a single device instance.
*/
typealias InstanceShard = List<Shard.App>

/**
* List of shards. Each shard for another device instance.
*/
typealias Shards = List<InstanceShard>

/**
* Collection of apps, tests, and test cases that can be used to calculate [Shards]
*/
typealias Apps = List<Shard.App>
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
@startuml
'https://plantuml.com/component-diagram

object calculateShards
abstract Apps {
List<App>
}

abstract Input {
one: App
abstract Shards {
List<Shard>
}

abstract Output {
many: List<App>
abstract Shard {
List<App>
}

class App {
Expand All @@ -26,11 +28,9 @@ name: String
duration: Long
}

calculateShards ..> Input : receive
calculateShards ..> Output : return

Input "1" o-- "1" App
Output "1" o-- "*" App
Apps "1" o-- "*" App
Shards "1" o-- "*" Shard
Shard "1" o-- "*" App
App "1" o-- "*" Test
Test "1" o-- "*" Case

Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ include(
":corellium:log",
":corellium:api",
":corellium:shard",
":corellium:shard:calculate",
":corellium:adapter",
)

Expand Down