diff --git a/docs/index.md b/docs/index.md index 307676a30e..c9f7a721c2 100644 --- a/docs/index.md +++ b/docs/index.md @@ -175,6 +175,13 @@ gcloud: ## The type of iOS test to run. TYPE must be one of: xctest, game-loop. Default: xctest # type: xctest + + ## The path to the application archive (.ipa file) for game-loop testing. + ## The path may be in the local filesystem or in Google Cloud Storage using gs:// notation. + ## This flag is only valid when --type=game-loop is also set + # app: + # - gs://bucket/additional.ipa OR path/to/local/ipa/file.ipa + ## Enables testing special app entitlements. Re-signs an app having special entitlements with a new application-identifier. ## This currently supports testing Push Notifications (aps-environment) entitlement for up to one app in a project. diff --git a/test_runner/flank.ios.yml b/test_runner/flank.ios.yml index 7dacd5d183..1da5dd0cab 100644 --- a/test_runner/flank.ios.yml +++ b/test_runner/flank.ios.yml @@ -104,6 +104,12 @@ gcloud: # - 2 # - 3 + ## The path to the application archive (.ipa file) for game-loop testing. + ## The path may be in the local filesystem or in Google Cloud Storage using gs:// notation. + ## This flag is only valid when --type=game-loop is also set + # app: + # - gs://bucket/additional.ipa OR path/to/local/ipa/file.ipa + ## The type of iOS test to run. TYPE must be one of: xctest, game-loop. Default: xctest # type: xctest diff --git a/test_runner/src/main/kotlin/ftl/args/CreateIosArgs.kt b/test_runner/src/main/kotlin/ftl/args/CreateIosArgs.kt index e4543145b0..45cd19f520 100644 --- a/test_runner/src/main/kotlin/ftl/args/CreateIosArgs.kt +++ b/test_runner/src/main/kotlin/ftl/args/CreateIosArgs.kt @@ -31,6 +31,7 @@ private fun createIosArgs( additionalIpas = gcloud.additionalIpas!!.map { it.normalizeFilePath() }, testTargets = flank.testTargets?.filterNotNull().orEmpty(), obfuscateDumpShards = obfuscate, + app = gcloud.app?.normalizeFilePath().orEmpty(), testSpecialEntitlements = gcloud.testSpecialEntitlements ?: false ) diff --git a/test_runner/src/main/kotlin/ftl/args/IosArgs.kt b/test_runner/src/main/kotlin/ftl/args/IosArgs.kt index 326a061902..f5141f42ae 100644 --- a/test_runner/src/main/kotlin/ftl/args/IosArgs.kt +++ b/test_runner/src/main/kotlin/ftl/args/IosArgs.kt @@ -15,6 +15,7 @@ data class IosArgs( val testTargets: List, val obfuscateDumpShards: Boolean, val additionalIpas: List, + val app: String, val testSpecialEntitlements: Boolean? ) : IArgs by commonArgs { @@ -46,6 +47,7 @@ IosArgs additional-ipas: ${ArgsToString.listToString(additionalIpas)} scenario-numbers: ${ArgsToString.listToString(scenarioNumbers)} type: ${type?.ymlName} + app: $app test-special-entitlements: $testSpecialEntitlements flank: diff --git a/test_runner/src/main/kotlin/ftl/args/ValidateIosArgs.kt b/test_runner/src/main/kotlin/ftl/args/ValidateIosArgs.kt index bc0bb848a0..52e74363b8 100644 --- a/test_runner/src/main/kotlin/ftl/args/ValidateIosArgs.kt +++ b/test_runner/src/main/kotlin/ftl/args/ValidateIosArgs.kt @@ -18,7 +18,16 @@ fun IosArgs.validate() = apply { assertGameloop() } -fun IosArgs.assertGameloop() { +private fun IosArgs.assertGameloop() { + validateApp() + validateScenarioNumbers() +} + +private fun IosArgs.validateApp() { + if (app.isNotEmpty() && type != Type.GAMELOOP) throw FlankConfigurationError("App cannot be defined if type is not equal to game-loop (IOS)") +} + +private fun IosArgs.validateScenarioNumbers() { if (scenarioNumbers.isNotEmpty() && (type != Type.GAMELOOP)) throw FlankConfigurationError("Scenario numbers defined but Type is not Game-loop.") scenarioNumbers.forEach { it.toIntOrNull() ?: throw FlankConfigurationError("Invalid scenario number provided - $it") } diff --git a/test_runner/src/main/kotlin/ftl/config/ios/IosGcloudConfig.kt b/test_runner/src/main/kotlin/ftl/config/ios/IosGcloudConfig.kt index 9e094033bb..642b3edb02 100644 --- a/test_runner/src/main/kotlin/ftl/config/ios/IosGcloudConfig.kt +++ b/test_runner/src/main/kotlin/ftl/config/ios/IosGcloudConfig.kt @@ -58,6 +58,15 @@ data class IosGcloudConfig @JsonIgnore constructor( @set:JsonProperty("additional-ipas") var additionalIpas: List? by data + @set:CommandLine.Option( + names = ["--app"], + description = ["The path to the application archive (.ipa file) for game-loop testing. " + + "The path may be in the local filesystem or in Google Cloud Storage using gs:// notation. " + + "This flag is only valid when --type=game-loop is also set"] + ) + @set:JsonProperty("app") + var app: String? by data + @set:CommandLine.Option( names = ["--test-special-entitlements"], description = ["Enables testing special app entitlements. Re-signs an app having special entitlements with a new" + @@ -84,6 +93,7 @@ data class IosGcloudConfig @JsonIgnore constructor( xctestrunFile = null xcodeVersion = null additionalIpas = emptyList() + app = null testSpecialEntitlements = false } } diff --git a/test_runner/src/test/kotlin/ftl/args/IosArgsTest.kt b/test_runner/src/test/kotlin/ftl/args/IosArgsTest.kt index 8740eada1a..78d11468d8 100644 --- a/test_runner/src/test/kotlin/ftl/args/IosArgsTest.kt +++ b/test_runner/src/test/kotlin/ftl/args/IosArgsTest.kt @@ -245,6 +245,7 @@ IosArgs - $testIpa2 scenario-numbers: type: xctest + app: test-special-entitlements: true flank: @@ -308,6 +309,7 @@ IosArgs additional-ipas: scenario-numbers: type: xctest + app: test-special-entitlements: false flank: @@ -1190,6 +1192,31 @@ IosArgs """.trimIndent() IosArgs.load(yaml).validate() } + + @Test(expected = FlankConfigurationError::class) + fun `should throw exception if app provided but not type equals gameloop`() { + val yaml = """ + gcloud: + test: $testPath + xctestrun-file: $testPath + results-dir: test + app: $testPath + """.trimIndent() + IosArgs.load(yaml).validate() + } + + @Test + fun `should not throw exception if app provided and type equals gameloop`() { + val yaml = """ + gcloud: + test: $testPath + xctestrun-file: $testPath + results-dir: test + type: game-loop + app: $testPath + """.trimIndent() + IosArgs.load(yaml).validate() + } } private fun IosArgs.Companion.load(yamlData: String, cli: IosRunCommand? = null): IosArgs =