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

887 Update sharding limit #915

Merged
merged 11 commits into from
Aug 3, 2020
Merged

887 Update sharding limit #915

merged 11 commits into from
Aug 3, 2020

Conversation

adamfilipow92
Copy link
Contributor

@adamfilipow92 adamfilipow92 commented Jul 24, 2020

Fixes #887

Test Plan

How do we know the code works?

For virtual devices, the limit should be set to 250.
For physical devices, the limit should be still 50.

In case when we have a virtual and physical device and shards limit set over the physical device limit, firebase returns an exception

Caused by: com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
{
  "code" : 400,
  "errors" : [ {
    "domain" : "global",
    "message" : "Given number of shards of 60 shards exceeds limit of 50 shards.",
    "reason" : "badRequest"


Solution

If the limit exceeds the physical limit and we have physical and virtual devices we split matrices by device type. This solution allows us to use the maximum limit on every device type.

Checklist

  • Documented
  • Unit tested
  • release_notes.md updated
  • Split devices by type and run on different matrices

@@ -39,3 +40,10 @@ fun Map<String, String>.asDevice(android: Boolean) =
orientation = getOrDefault("orientation", version)
)
}

fun Device.isVirtual(projectId: String) = if (this.isVirtual == null) AndroidCatalog.isVirtualDevice(model, projectId).takeIf { it }?.apply {
isVirtual = this
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is Boolean in current scope so i guess also fits better then apply.

} ?: false
else this.isVirtual ?: false

fun List<Device>.check(projectId: String) = forEach { it.isVirtual(projectId) }.let { this }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fun List<Device>.check(projectId: String) = forEach { it.isVirtual(projectId) }.let { this }
fun List<Device>.check(projectId: String) = apply { forEach { it.isVirtual(projectId) } }

Comment on lines 44 to 45
fun Device.isVirtual(projectId: String) = if (this.isVirtual == null) AndroidCatalog.isVirtualDevice(model, projectId).takeIf { it }?.apply {
isVirtual = this
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fun Device.isVirtual(projectId: String) = if (this.isVirtual == null) AndroidCatalog.isVirtualDevice(model, projectId).takeIf { it }?.apply {
isVirtual = this
fun Device.isVirtual(projectId: String) = if (this.isVirtual == null) AndroidCatalog.isVirtualDevice(model, projectId).takeIf { it }?.also {
isVirtual = it

}
return@withTimeoutOrNull this
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason for returning CoroutineScope?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this is redundant I should remove it. Thanks!

val testMatrices = mutableListOf<Deferred<TestMatrix>>()
val allTestShardChunks = mutableListOf<List<String>>()
val ignoredTestsShardChunks = mutableListOf<List<String>>()

val history = GcToolResults.createToolResultsHistory(args)
val otherGcsFiles = args.uploadOtherFiles(runGcsPath)
val additionalApks = args.uploadAdditionalApks(runGcsPath)
val argsList = if (args.shouldSplitRuns()) args.splitConfigurationByDeviceType() else listOf(args)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

argsList is a little bit generic in this context maybe deviceConfigurations or deviceArgs will fits better?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deviceArgs fits great, thanks!

@adamfilipow92 adamfilipow92 force-pushed the 887-Update-sharding-limit branch from a191b78 to 4cbfff1 Compare July 28, 2020 16:03
@adamfilipow92 adamfilipow92 marked this pull request as ready for review July 28, 2020 16:08
}

@Test(expected = FlankFatalError::class)
fun `should throw when physical devices and maximum test shards limit exceed`() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fun `should throw when physical devices and maximum test shards limit exceed`() {
fun `should throw when maximum test shards for physical devices limit exceeded`() {

}

@Test(expected = FlankFatalError::class)
fun `should throw when virtual devices and maximum test shards limit exceed`() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fun `should throw when virtual devices and maximum test shards limit exceed`() {
fun `should throw when maximum test shards for virtual devices limit exceeded`() {

isVirtual = it
} else isVirtual ?: false

fun List<Device>.check(projectId: String) = apply { forEach { it.isVirtual(projectId) } }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fun List<Device>.check(projectId: String) = apply { forEach { it.isVirtual(projectId) } }
fun List<Device>.resolve(projectId: String) = apply { forEach { it.isVirtual(projectId) } }

@@ -23,6 +25,7 @@ data class AndroidArgs(
) : IArgs by commonArgs {
companion object : AndroidArgsCompanion()

// override val maxTestShards: Int = calculateMaxTestShards(commonArgs.maxTestShards)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete if unused

xctestrunZip = gcloud.test!!.processFilePath("from test"),
xctestrunFile = gcloud.xctestrunFile!!.processFilePath("from xctestrun-file"),
xcodeVersion = gcloud.xcodeVersion,
testTargets = flank.testTargets!!.filterNotNull()
)

private fun convertToShardCount(inputValue: Int): Int =
Copy link
Contributor

@piotradamczyk5 piotradamczyk5 Jul 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about single line without : Int ?

if (!inVirtualRange) throwMaxTestShardsLimitExceeded()
}

private fun AndroidArgs.throwMaxTestShardsLimitExceeded() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return type could be Nothing for self documentation

@@ -83,3 +86,17 @@ val AndroidArgs.isInstrumentationTest
val AndroidArgs.isRoboTest
get() = appApk != null &&
(roboDirectives.isNotEmpty() || roboScript != null)

fun AndroidArgs.containsVirtualDevices() = devices.any { it.isVirtual!! }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it.isVirtual ?: false is safer call. WDYT?


fun AndroidArgs.containsPhysicalDevices() = devices.any { !it.isVirtual!! }

fun AndroidArgs.shouldSplitRuns() = containsPhysicalDevices() && maxTestShards > 50
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should not we use AVAILABLE_PHYSICAL_SHARD_COUNT_RANGE.last ?

flank:
disable-sharding: false
max-test-shards: 40

Copy link
Contributor

@piotradamczyk5 piotradamczyk5 Jul 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 empty line could be skipped ;) please check other config files

@@ -1,6 +1,8 @@
package ftl.args

import ftl.args.yml.AppTestPair
import ftl.config.resolve
import ftl.config.isVirtual
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that these imports are unused

@@ -12,9 +12,9 @@ data class Device(
val model: String,
val version: String,
val locale: String = defaultLocale,
val orientation: String = defaultOrientation
val orientation: String = defaultOrientation,
val isVirtual: Boolean? = null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isVirtual shouldn't be nullable. We don't need nulls in later calculations.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright! Changed! 👍

@adamfilipow92 adamfilipow92 force-pushed the 887-Update-sharding-limit branch from 48bc561 to 09c1664 Compare July 31, 2020 10:36
@adamfilipow92 adamfilipow92 merged commit 052cd87 into master Aug 3, 2020
@adamfilipow92 adamfilipow92 deleted the 887-Update-sharding-limit branch August 3, 2020 11:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Update sharding limit
3 participants