Skip to content

Commit

Permalink
feat(apple): rework apple to support additional targets
Browse files Browse the repository at this point in the history
  • Loading branch information
Malinskiy committed Feb 16, 2024
1 parent 012f6b5 commit 015f7d1
Show file tree
Hide file tree
Showing 220 changed files with 1,137 additions and 936 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import com.malinskiy.marathon.config.serialization.ConfigurationFactory
import com.malinskiy.marathon.config.vendor.VendorConfiguration
import com.malinskiy.marathon.di.marathonStartKoin
import com.malinskiy.marathon.exceptions.ExceptionsReporterFactory
import com.malinskiy.marathon.apple.ios.AppleVendor
import com.malinskiy.marathon.apple.ios.IosVendor
import com.malinskiy.marathon.log.MarathonLogging
import org.koin.core.context.stopKoin
import org.koin.dsl.module
Expand Down Expand Up @@ -66,7 +66,7 @@ private fun execute(cliConfiguration: CliConfiguration) {
val vendorConfiguration = configuration.vendorConfiguration
val modules = when (vendorConfiguration) {
is VendorConfiguration.IOSConfiguration -> {
AppleVendor + module { single { vendorConfiguration } }
IosVendor + module { single { vendorConfiguration } }
}
is VendorConfiguration.AndroidConfiguration -> {
AndroidVendor + module { single { vendorConfiguration } } + listOf(adamModule)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import com.malinskiy.marathon.config.exceptions.ConfigurationException
import com.malinskiy.marathon.config.serialization.time.InstantTimeProviderImpl
import com.malinskiy.marathon.config.serialization.yaml.SerializeModule
import com.malinskiy.marathon.config.vendor.VendorConfiguration
import com.malinskiy.marathon.config.vendor.ios.AppleTestBundleConfiguration
import com.malinskiy.marathon.config.vendor.ios.SshAuthentication
import com.malinskiy.marathon.config.vendor.apple.AppleTestBundleConfiguration
import com.malinskiy.marathon.config.vendor.apple.SshAuthentication
import org.apache.commons.text.StringSubstitutor
import org.apache.commons.text.lookup.StringLookupFactory
import java.io.File
Expand Down Expand Up @@ -105,6 +105,46 @@ class ConfigurationFactory(
ssh = optionalSshConfiguration,
)
}
is VendorConfiguration.MacosConfiguration -> {
// Any relative path specified in Marathonfile should be resolved against the directory Marathonfile is in
val macosConfiguration: VendorConfiguration.MacosConfiguration = configuration.vendorConfiguration
val resolvedBundle = macosConfiguration.bundle?.let {
val resolvedDerivedDataDir = it.derivedDataDir?.let { ddd -> marathonfileDir.resolve(ddd) }
val resolvedApplication = it.application?.let { ddd -> marathonfileDir.resolve(ddd) }
val resolvedTestApplication = it.testApplication?.let { ddd -> marathonfileDir.resolve(ddd) }
val resolvedExtraApplications = it.extraApplications?.map { ddd -> marathonfileDir.resolve(ddd) }

AppleTestBundleConfiguration(
resolvedApplication,
resolvedTestApplication,
resolvedExtraApplications,
resolvedDerivedDataDir
).apply { validate() }
}
val optionalDevices = configuration.vendorConfiguration.devicesFile?.resolveAgainst(marathonfileDir)
?: marathonfileDir.resolve("Marathondevices")

val optionalknownHostsPath = macosConfiguration.ssh.knownHostsPath?.resolveAgainst(marathonfileDir)
val optionalSshAuthentication = when (macosConfiguration.ssh.authentication) {
is SshAuthentication.PasswordAuthentication -> macosConfiguration.ssh.authentication
is SshAuthentication.PublicKeyAuthentication -> macosConfiguration.ssh.authentication.copy(
username = macosConfiguration.ssh.authentication.username,
key = macosConfiguration.ssh.authentication.key.resolveAgainst(marathonfileDir)
)

null -> null
}
val optionalSshConfiguration = macosConfiguration.ssh.copy(
authentication = optionalSshAuthentication,
knownHostsPath = optionalknownHostsPath,
)

configuration.vendorConfiguration.copy(
bundle = resolvedBundle,
devicesFile = optionalDevices,
ssh = optionalSshConfiguration,
)
}

VendorConfiguration.StubVendorConfiguration -> configuration.vendorConfiguration
is VendorConfiguration.EmptyVendorConfiguration -> throw ConfigurationException("No vendor configuration specified")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,19 @@ import com.malinskiy.marathon.config.vendor.android.TestAccessConfiguration
import com.malinskiy.marathon.config.vendor.android.TestParserConfiguration
import com.malinskiy.marathon.config.vendor.android.ThreadingConfiguration
import com.malinskiy.marathon.config.vendor.android.TimeoutConfiguration
import com.malinskiy.marathon.config.vendor.ios.AppleTestBundleConfiguration
import com.malinskiy.marathon.config.vendor.ios.LifecycleConfiguration
import com.malinskiy.marathon.config.vendor.ios.PermissionsConfiguration
import com.malinskiy.marathon.config.vendor.ios.RsyncConfiguration
import com.malinskiy.marathon.config.vendor.ios.SigningConfiguration
import com.malinskiy.marathon.config.vendor.ios.SshConfiguration
import com.malinskiy.marathon.config.vendor.ios.XcresultConfiguration
import com.malinskiy.marathon.config.vendor.apple.AppleTestBundleConfiguration
import com.malinskiy.marathon.config.vendor.apple.ios.LifecycleConfiguration
import com.malinskiy.marathon.config.vendor.apple.ios.PermissionsConfiguration
import com.malinskiy.marathon.config.vendor.apple.RsyncConfiguration
import com.malinskiy.marathon.config.vendor.apple.ios.SigningConfiguration
import com.malinskiy.marathon.config.vendor.apple.SshConfiguration
import com.malinskiy.marathon.config.vendor.apple.ios.XcresultConfiguration
import java.io.File
import com.malinskiy.marathon.config.vendor.ios.ScreenRecordConfiguration as AppleScreenRecordConfiguration
import com.malinskiy.marathon.config.vendor.ios.ThreadingConfiguration as IosThreadingConfiguration
import com.malinskiy.marathon.config.vendor.ios.TimeoutConfiguration as AppleTimeoutConfiguration
import com.malinskiy.marathon.config.vendor.apple.TestParserConfiguration as AppleTestParserConfiguration
import com.malinskiy.marathon.config.vendor.apple.ios.ScreenRecordConfiguration as IosScreenRecordConfiguration
import com.malinskiy.marathon.config.vendor.apple.ThreadingConfiguration as AppleThreadingConfiguration
import com.malinskiy.marathon.config.vendor.apple.ios.TimeoutConfiguration as IosTimeoutConfiguration
import com.malinskiy.marathon.config.vendor.apple.macos.TimeoutConfiguration as MacosTimeoutConfiguration1

const val DEFAULT_INIT_TIMEOUT_MILLIS = 30_000
const val DEFAULT_AUTO_GRANT_PERMISSION = false
Expand All @@ -42,6 +44,7 @@ const val DEFAULT_WAIT_FOR_DEVICES_TIMEOUT = 30000L
@JsonSubTypes(
JsonSubTypes.Type(value = VendorConfiguration.AndroidConfiguration::class, name = "Android"),
JsonSubTypes.Type(value = VendorConfiguration.IOSConfiguration::class, name = "iOS"),
JsonSubTypes.Type(value = VendorConfiguration.MacosConfiguration::class, name = "macOS"),
JsonSubTypes.Type(value = VendorConfiguration.StubVendorConfiguration::class, name = "stub"),
JsonSubTypes.Type(value = VendorConfiguration.EmptyVendorConfiguration::class, name = "empty"),
)
Expand Down Expand Up @@ -152,18 +155,43 @@ sealed class VendorConfiguration {
@JsonProperty("ssh") val ssh: SshConfiguration = SshConfiguration(),

@JsonProperty("xcresult") val xcresult: XcresultConfiguration = XcresultConfiguration(),
@JsonProperty("screenRecordConfiguration") val screenRecordConfiguration: AppleScreenRecordConfiguration = AppleScreenRecordConfiguration(),
@JsonProperty("screenRecordConfiguration") val screenRecordConfiguration: IosScreenRecordConfiguration = IosScreenRecordConfiguration(),
@JsonProperty("xctestrunEnv") val xctestrunEnv: Map<String, String> = emptyMap(),
@JsonProperty("lifecycle") val lifecycleConfiguration: LifecycleConfiguration = LifecycleConfiguration(),
@JsonProperty("permissions") val permissions: PermissionsConfiguration = PermissionsConfiguration(),
@JsonProperty("timeoutConfiguration") val timeoutConfiguration: AppleTimeoutConfiguration = AppleTimeoutConfiguration(),
@JsonProperty("threadingConfiguration") val threadingConfiguration: IosThreadingConfiguration = IosThreadingConfiguration(),
@JsonProperty("timeoutConfiguration") val timeoutConfiguration: IosTimeoutConfiguration = IosTimeoutConfiguration(),
@JsonProperty("threadingConfiguration") val threadingConfiguration: AppleThreadingConfiguration = AppleThreadingConfiguration(),
@JsonProperty("hideRunnerOutput") val hideRunnerOutput: Boolean = false,
@JsonProperty("compactOutput") val compactOutput: Boolean = false,
@JsonProperty("rsync") val rsync: RsyncConfiguration = RsyncConfiguration(),
@JsonProperty("xcodebuildTestArgs") val xcodebuildTestArgs: Map<String, String> = emptyMap(),
@JsonProperty("dataContainerClear") val dataContainerClear: Boolean = false,
@JsonProperty("testParserConfiguration") val testParserConfiguration: com.malinskiy.marathon.config.vendor.ios.TestParserConfiguration = com.malinskiy.marathon.config.vendor.ios.TestParserConfiguration.NmTestParserConfiguration(),
@JsonProperty("testParserConfiguration") val testParserConfiguration: AppleTestParserConfiguration = AppleTestParserConfiguration.NmTestParserConfiguration(),

@JsonProperty("signing") val signing: SigningConfiguration = SigningConfiguration(),
) : VendorConfiguration() {
fun validate() {
ssh.validate()

val testBundleConfiguration = bundle ?: throw ConfigurationException("bundles must contain at least one valid entry")
testBundleConfiguration.validate()
}
}

data class MacosConfiguration(
@JsonProperty("bundle") val bundle: AppleTestBundleConfiguration? = null,
@JsonProperty("devices") val devicesFile: File? = null,
@JsonProperty("ssh") val ssh: SshConfiguration = SshConfiguration(),

@JsonProperty("xcresult") val xcresult: XcresultConfiguration = XcresultConfiguration(),
@JsonProperty("xctestrunEnv") val xctestrunEnv: Map<String, String> = emptyMap(),
@JsonProperty("timeoutConfiguration") val timeoutConfiguration: MacosTimeoutConfiguration1 = MacosTimeoutConfiguration1(),
@JsonProperty("threadingConfiguration") val threadingConfiguration: AppleThreadingConfiguration = AppleThreadingConfiguration(),
@JsonProperty("hideRunnerOutput") val hideRunnerOutput: Boolean = false,
@JsonProperty("compactOutput") val compactOutput: Boolean = false,
@JsonProperty("rsync") val rsync: RsyncConfiguration = RsyncConfiguration(),
@JsonProperty("xcodebuildTestArgs") val xcodebuildTestArgs: Map<String, String> = emptyMap(),
@JsonProperty("testParserConfiguration") val testParserConfiguration: AppleTestParserConfiguration = AppleTestParserConfiguration.NmTestParserConfiguration(),

@JsonProperty("signing") val signing: SigningConfiguration = SigningConfiguration(),
) : VendorConfiguration() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package com.malinskiy.marathon.config.vendor.ios
package com.malinskiy.marathon.config.vendor.apple

import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonProperty
import com.malinskiy.marathon.config.exceptions.ConfigurationException
import com.malinskiy.marathon.config.serialization.yaml.FileListProvider
import java.io.File
import java.io.FileOutputStream
import java.util.zip.ZipFile
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.malinskiy.marathon.config.vendor.ios
package com.malinskiy.marathon.config.vendor.apple

import com.fasterxml.jackson.annotation.JsonProperty

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.malinskiy.marathon.config.vendor.ios
package com.malinskiy.marathon.config.vendor.apple

import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.annotation.JsonSubTypes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.malinskiy.marathon.config.vendor.ios
package com.malinskiy.marathon.config.vendor.apple

import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.malinskiy.marathon.config.vendor.ios
package com.malinskiy.marathon.config.vendor.apple

import com.fasterxml.jackson.annotation.JsonProperty

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.malinskiy.marathon.config.vendor.ios
package com.malinskiy.marathon.config.vendor.apple

import com.fasterxml.jackson.annotation.JsonProperty

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.malinskiy.marathon.config.vendor.ios
package com.malinskiy.marathon.config.vendor.apple.ios

import com.fasterxml.jackson.annotation.JsonProperty

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.malinskiy.marathon.config.vendor.ios
package com.malinskiy.marathon.config.vendor.apple.ios

import com.fasterxml.jackson.annotation.JsonProperty

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.malinskiy.marathon.config.vendor.ios
package com.malinskiy.marathon.config.vendor.apple.ios

import com.fasterxml.jackson.annotation.JsonProperty

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.malinskiy.marathon.config.vendor.ios
package com.malinskiy.marathon.config.vendor.apple.ios

import com.fasterxml.jackson.annotation.JsonProperty

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.malinskiy.marathon.config.vendor.ios
package com.malinskiy.marathon.config.vendor.apple.ios

import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.malinskiy.marathon.config.vendor.ios
package com.malinskiy.marathon.config.vendor.apple.ios

import com.fasterxml.jackson.annotation.JsonProperty
import java.time.Duration
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.malinskiy.marathon.config.vendor.ios
package com.malinskiy.marathon.config.vendor.apple.ios

import com.fasterxml.jackson.annotation.JsonProperty

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.malinskiy.marathon.config.vendor.ios
package com.malinskiy.marathon.config.vendor.apple.ios

import com.fasterxml.jackson.annotation.JsonProperty
import java.time.Duration
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.malinskiy.marathon.config.vendor.ios
package com.malinskiy.marathon.config.vendor.apple.ios

import com.fasterxml.jackson.annotation.JsonProperty

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.malinskiy.marathon.config.vendor.ios
package com.malinskiy.marathon.config.vendor.apple.ios

import com.fasterxml.jackson.annotation.JsonProperty

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.malinskiy.marathon.config.vendor.apple.macos

import com.fasterxml.jackson.annotation.JsonProperty
import java.time.Duration
import java.time.temporal.ChronoUnit

/**
* @param shell default timeout for shell commands
* @param shellIdle default idling timeout for shell commands
* @param reachability timeout for inactive remote host
*/
data class TimeoutConfiguration(
@JsonProperty("shell") var shell: Duration = Duration.ofSeconds(30),
@JsonProperty("shellIdle") var shellIdle: Duration = Duration.ofSeconds(30),
@JsonProperty("reachability") var reachability: Duration = Duration.ofSeconds(5),
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator
import com.malinskiy.marathon.config.serialization.time.InstantTimeProvider
import com.malinskiy.marathon.config.vendor.VendorConfiguration
import com.malinskiy.marathon.config.vendor.ios.AppleTestBundleConfiguration
import com.malinskiy.marathon.config.vendor.ios.LifecycleConfiguration
import com.malinskiy.marathon.config.vendor.ios.RsyncConfiguration
import com.malinskiy.marathon.config.vendor.ios.SshAuthentication
import com.malinskiy.marathon.config.vendor.ios.SshConfiguration
import com.malinskiy.marathon.config.vendor.apple.AppleTestBundleConfiguration
import com.malinskiy.marathon.config.vendor.apple.ios.LifecycleConfiguration
import com.malinskiy.marathon.config.vendor.apple.RsyncConfiguration
import com.malinskiy.marathon.config.vendor.apple.SshAuthentication
import com.malinskiy.marathon.config.vendor.apple.SshConfiguration
import org.amshove.kluent.shouldBeEqualTo
import org.junit.jupiter.api.Test
import java.io.File
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.malinskiy.marathon.config.vendor.ios

import com.malinskiy.marathon.config.exceptions.ConfigurationException
import com.malinskiy.marathon.config.vendor.IOSConfigurationTest
import com.malinskiy.marathon.config.vendor.apple.AppleTestBundleConfiguration
import org.amshove.kluent.invoking
import org.amshove.kluent.shouldThrow
import org.junit.jupiter.api.Test
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/kotlin/com/malinskiy/marathon/Marathon.kt
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,14 @@ class Marathon(
throw ConfigurationException("Unknown test parser type for ${testParser::class}, should inherit from either ${LocalTestParser::class.simpleName} or ${RemoteTestParser::class.simpleName}")
}
}
}.let { println("Took $it ms") }
}.let { log.debug { "Parsing took $it ms" } }

usageTracker.meta(
version = BuildConfig.VERSION, releaseMode = BuildConfig.RELEASE_MODE, vendor = when (configuration.vendorConfiguration) {
is VendorConfiguration.AndroidConfiguration -> "android"
is VendorConfiguration.EmptyVendorConfiguration -> "empty"
is VendorConfiguration.IOSConfiguration -> "ios"
is VendorConfiguration.MacosConfiguration -> "macos"
VendorConfiguration.StubVendorConfiguration -> "testing"
}
)
Expand Down
1 change: 1 addition & 0 deletions core/src/main/kotlin/com/malinskiy/marathon/di/Modules.kt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ val coreModule = module {
fun marathonStartKoin(configuration: Configuration, modules: List<Module>): KoinApplication {
val configurationModule = module {
single { configuration }
single { configuration.vendorConfiguration }
}

return startKoin {
Expand Down
31 changes: 31 additions & 0 deletions vendor/vendor-apple/base/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,14 +1,45 @@
import com.malinskiy.marathon.buildsystem.XcresulttoolPlugin

plugins {
`java-library`
jacoco
id("org.jetbrains.kotlin.jvm")
id("org.jetbrains.dokka")
}

apply<XcresulttoolPlugin>()

dependencies {
api(Libraries.kotlinStdLib)
api(Libraries.kotlinCoroutines)
api(Libraries.kotlinLogging)
api(Libraries.kotlinReflect)
api(Libraries.logbackClassic)
api(Libraries.ddPlist)
api(Libraries.guava)
api(Libraries.rsync4j)

api(Libraries.gson)
api(Libraries.jacksonKotlin)
api(Libraries.jacksonYaml)
api(Libraries.jansi)
api(Libraries.kotlinProcess)
api(Libraries.sshj)

api(project(":core"))

testImplementation(TestLibraries.kluent)
testImplementation(TestLibraries.assertk)
testImplementation(TestLibraries.mockitoKotlin)
testImplementation(TestLibraries.testContainers)
testImplementation(TestLibraries.testContainersJupiter)
testImplementation(TestLibraries.junit5)
testImplementation(TestLibraries.coroutinesTest)
testRuntimeOnly(TestLibraries.jupiterEngine)
}

setupDeployment()
setupKotlinCompiler()
setupTestTask()

tasks.findByPath("sourcesJar")?.dependsOn(tasks.findByPath("generateXcresulttoolSource"))
Loading

0 comments on commit 015f7d1

Please sign in to comment.