-
Notifications
You must be signed in to change notification settings - Fork 118
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#911 Refactor Doctor and add json tree validation
- Loading branch information
Piotr Adamczyk
committed
Jul 31, 2020
1 parent
0b9b937
commit 9973baa
Showing
7 changed files
with
145 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,64 @@ | ||
package ftl.doctor | ||
|
||
import com.fasterxml.jackson.databind.JsonNode | ||
import com.google.common.annotations.VisibleForTesting | ||
import ftl.args.AndroidArgsCompanion | ||
import ftl.args.ArgsHelper | ||
import ftl.args.IArgs | ||
import ftl.config.loadAndroidConfig | ||
import ftl.config.loadIosConfig | ||
import ftl.util.FlankFatalError | ||
import ftl.util.loadFile | ||
import java.io.Reader | ||
import java.lang.StringBuilder | ||
import java.nio.file.Path | ||
|
||
object Doctor { | ||
fun validateYaml(args: IArgs.ICompanion, data: Path): String { | ||
if (!data.toFile().exists()) return "Skipping yaml validation. No file at path $data" | ||
return validateYaml(args, loadFile(data)) + preloadConfiguration(data, args is AndroidArgsCompanion) | ||
} | ||
|
||
@VisibleForTesting | ||
internal fun validateYaml(args: IArgs.ICompanion, data: Reader): String { | ||
var result = "" | ||
val parsed = ArgsHelper.yamlMapper.readTree(data) | ||
fun validateYaml(args: IArgs.ICompanion, data: Path): String { | ||
if (!data.toFile().exists()) return "Skipping yaml validation. No file at path $data" | ||
return validateYaml(args, loadFile(data)) + preloadConfiguration(data, args is AndroidArgsCompanion) | ||
} | ||
|
||
val validArgs = args.validArgs | ||
val parsedArgs = mutableMapOf<String, List<String>>() | ||
@VisibleForTesting | ||
internal fun validateYaml(args: IArgs.ICompanion, data: Reader) = | ||
runCatching { ArgsHelper.yamlMapper.readTree(data) } | ||
.onFailure { return it.message ?: "Unknown error when parsing tree" } | ||
.getOrNull() | ||
?.run { validateYamlKeys(args) } | ||
.orEmpty() | ||
|
||
for (child in parsed.fields()) { | ||
val key = child.key | ||
val values = mutableListOf<String>() | ||
child.value.fields().forEach { values.add(it.key) } | ||
private fun JsonNode.validateYamlKeys(args: IArgs.ICompanion) = StringBuilder().apply { | ||
append(validateTopLevelKeys(args)) | ||
args.validArgs.forEach { (topLevelKey, validArgsKeys) -> | ||
append(validateNestedKeys(topLevelKey, validArgsKeys)) | ||
} | ||
}.toString() | ||
|
||
parsedArgs[key] = values | ||
} | ||
private fun JsonNode.validateTopLevelKeys(args: IArgs.ICompanion) = | ||
(parseArgs().keys - args.validArgs.keys) | ||
.takeIf { it.isNotEmpty() } | ||
?.let { unknownKeys -> "Unknown top level keys: $unknownKeys\n" } | ||
.orEmpty() | ||
|
||
val unknownTopLevelKeys = parsedArgs.keys - validArgs.keys | ||
if (unknownTopLevelKeys.isNotEmpty()) result += "Unknown top level keys: $unknownTopLevelKeys\n" | ||
private fun JsonNode.parseArgs() = mutableMapOf<String, List<String>>().apply { | ||
for (child in fields()) { | ||
this[child.key] = child.value.fields().asSequence().map { it.key }.toList() | ||
} | ||
} | ||
|
||
validArgs.forEach { (topLevelKey, keyList) -> | ||
val parsedKeys = mutableListOf<String>() | ||
parsed[topLevelKey]?.fields()?.forEach { parsedKeys.add(it.key) } | ||
val unknownKeys = parsedKeys - keyList | ||
if (unknownKeys.isNotEmpty()) result += "Unknown keys in $topLevelKey -> $unknownKeys\n" | ||
} | ||
private fun JsonNode.validateNestedKeys(topLevelKey: String, validArgsKeys: List<String>) = | ||
nestedKeysFor(topLevelKey) | ||
.minus(validArgsKeys) | ||
.takeIf { it.isNotEmpty() } | ||
?.let { "Unknown keys in $topLevelKey -> $it\n" } | ||
.orEmpty() | ||
|
||
return result | ||
} | ||
private fun JsonNode.nestedKeysFor(topLevelKey: String) = | ||
this[topLevelKey]?.fields()?.asSequence()?.map { it.key }?.toList().orEmpty() | ||
|
||
private fun preloadConfiguration(data: Path, isAndroid: Boolean) = try { | ||
private fun preloadConfiguration(data: Path, isAndroid: Boolean) = | ||
try { | ||
if (isAndroid) loadAndroidConfig(data) else loadIosConfig(data) | ||
"" | ||
} catch (e: Exception) { | ||
} catch (e: FlankFatalError) { | ||
e.message | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
test_runner/src/test/kotlin/ftl/fixtures/flank_android_failed_configuration.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
gcloud: | ||
app: /Users/no/workspace/fladle/sample/build/outputs/apk/debug/sample-debug.apk | ||
test: /Users/no/workspace/fladle/sample/build/outputs/apk/androidTest/debug/sample-debug-androidTest.apk | ||
device: | ||
- model: Nexus5 | ||
version: 23 | ||
use-orchestrator: true | ||
auto-google-login: false | ||
record-video: true | ||
performance-metrics: true | ||
timeout: 15m | ||
environment-variables: | ||
clearPackageData: true | ||
test-targets: | ||
- class com.osacky.flank.gradle.sample.ExampleInstrumentedTest#seeView | ||
num-flaky-test-attempts: 1 | ||
flank: | ||
additional-app-test-apks: | ||
app: ../main/app/build/output/apk/debug/app.apk | ||
test: ../main/app/build/output/apk/androidTest/debug/app-test.apk | ||
app: ../sample/app/build/output/apk/debug/sample-app.apk | ||
test: ../sample/app/build/output/apk/androidTest/debug/sample-app-test.apk | ||
test: ../feature/room/build/output/apk/androidTest/debug/feature-room-test.apk | ||
test: ../library/databases/build/output/apk/androidTest/debug/sample-databases-test.apk |
24 changes: 24 additions & 0 deletions
24
test_runner/src/test/kotlin/ftl/fixtures/flank_android_failed_tree.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
gcloud: | ||
app: /Users/no/workspace/fladle/sample/build/outputs/apk/debug/sample-debug.apk | ||
test: /Users/no/workspace/fladle/sample/build/outputs/apk/androidTest/debug/sample-debug-androidTest.apk | ||
device: | ||
- model: Nexus5 | ||
version: 23 | ||
use-orchestrator: true | ||
auto-google-login: false | ||
record-video: true | ||
performance-metrics: true | ||
timeout: 15m | ||
environment-variables: | ||
clearPackageData: true | ||
test-targets: | ||
- class com.osacky.flank.gradle.sample.ExampleInstrumentedTest#seeView | ||
num-flaky-test-attempts: 1 | ||
flank: | ||
additional-app-test-apks: | ||
- app: ../main/app/build/output/apk/debug/app.apk | ||
test: ../main/app/build/output/apk/androidTest/debug/app-test.apk | ||
app: ../sample/app/build/output/apk/debug/sample-app.apk | ||
test: ../sample/app/build/output/apk/androidTest/debug/sample-app-test.apk | ||
test: ../feature/room/build/output/apk/androidTest/debug/feature-room-test.apk | ||
test: ../library/databases/build/output/apk/androidTest/debug/sample-databases-test.apk |