Skip to content

Commit

Permalink
Avoid using Koin GlobalContext (#60)
Browse files Browse the repository at this point in the history
  • Loading branch information
technoir42 authored Jul 1, 2024
1 parent 298e2c1 commit 7976ff2
Show file tree
Hide file tree
Showing 21 changed files with 73 additions and 290 deletions.
42 changes: 7 additions & 35 deletions core/src/main/kotlin/com/malinskiy/marathon/Marathon.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,33 @@ import com.malinskiy.marathon.execution.TestParser
import com.malinskiy.marathon.execution.TestShard
import com.malinskiy.marathon.execution.progress.ProgressReporter
import com.malinskiy.marathon.io.AttachmentManager
import com.malinskiy.marathon.log.MarathonLogConfigurator
import com.malinskiy.marathon.log.MarathonLogging
import com.malinskiy.marathon.report.logs.LogsProvider
import com.malinskiy.marathon.test.Test
import com.malinskiy.marathon.test.toTestName
import com.malinskiy.marathon.time.Timer
import com.malinskiy.marathon.vendor.VendorConfiguration
import kotlinx.coroutines.runBlocking
import org.koin.core.context.stopKoin
import java.util.*
import kotlin.coroutines.coroutineContext

private val log = MarathonLogging.logger {}

class Marathon(
val configuration: Configuration,
private val componentInfoExtractor: ComponentInfoExtractor,
private val deviceProvider: DeviceProvider,
private val tracker: TrackerInternal,
private val analytics: Analytics,
private val testCacheLoader: TestCacheLoader,
private val testCacheSaver: TestCacheSaver,
private val testParser: TestParser,
private val cachedTestsReporter: CacheTestReporter,
private val progressReporter: ProgressReporter,
private val attachmentManager: AttachmentManager,
private val strictRunChecker: StrictRunChecker,
private val logConfigurator: MarathonLogConfigurator,
private val logsProvider: LogsProvider,
private val track: Track,
private val timer: Timer
Expand All @@ -53,41 +57,13 @@ class Marathon(
private val configurationValidator = LogicalConfigurationValidator()
private val strictRunProcessor = StrictRunProcessor(configuration.strictRunFilterConfiguration)

private lateinit var deviceProvider: DeviceProvider
private lateinit var testParser: TestParser
private lateinit var scheduler: Scheduler
private lateinit var hook: ShutdownHook

private fun configureLogging(vendorConfiguration: VendorConfiguration) {
MarathonLogging.debug = configuration.debug

vendorConfiguration.logConfigurator()?.configure(vendorConfiguration)
}

private suspend fun loadDeviceProvider(vendorConfiguration: VendorConfiguration): DeviceProvider {
val vendorDeviceProvider = vendorConfiguration.deviceProvider()
?: ServiceLoader.load(DeviceProvider::class.java).first()

vendorDeviceProvider.initialize(configuration.vendorConfiguration)
return vendorDeviceProvider
}

private fun loadTestParser(vendorConfiguration: VendorConfiguration): TestParser {
val vendorTestParser = vendorConfiguration.testParser()
if (vendorTestParser != null) {
return vendorTestParser
}
val loader = ServiceLoader.load(TestParser::class.java)
return loader.first()
}

private fun loadComponentInfoExtractor(vendorConfiguration: VendorConfiguration): ComponentInfoExtractor {
val componentInfoExtractor = vendorConfiguration.componentInfoExtractor()
if (componentInfoExtractor != null) {
return componentInfoExtractor
}
val loader = ServiceLoader.load(ComponentInfoExtractor::class.java)
return loader.first()
logConfigurator.configure(vendorConfiguration)
}

fun run() = runBlocking {
Expand All @@ -113,7 +89,7 @@ class Marathon(
suspend fun runAsync(): Boolean {
start()

val componentInfo = loadComponentInfoExtractor(configuration.vendorConfiguration).extract(configuration)
val componentInfo = componentInfoExtractor.extract(configuration)
scheduleTests(componentInfo)

return stopAndWaitForCompletion()
Expand All @@ -122,8 +98,6 @@ class Marathon(
override suspend fun start() {
configureLogging(configuration.vendorConfiguration)

testParser = loadTestParser(configuration.vendorConfiguration)
deviceProvider = loadDeviceProvider(configuration.vendorConfiguration)
logger.debug { "Finished loading device provider" }

configurationValidator.validate(configuration)
Expand Down Expand Up @@ -177,8 +151,6 @@ class Marathon(
throw throwable
} finally {
hook.uninstall()

stopKoin()
}
return progressReporter.aggregateResult()
}
Expand Down
11 changes: 5 additions & 6 deletions core/src/main/kotlin/com/malinskiy/marathon/di/Modules.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@ import com.malinskiy.marathon.cache.test.key.VersionNameProvider
import com.malinskiy.marathon.execution.Configuration
import com.malinskiy.marathon.execution.ConfigurationStrictRunChecker
import com.malinskiy.marathon.execution.StrictRunChecker
import com.malinskiy.marathon.json.FileSerializer
import com.malinskiy.marathon.execution.progress.ProgressReporter
import com.malinskiy.marathon.io.AttachmentManager
import com.malinskiy.marathon.io.CachedFileHasher
import com.malinskiy.marathon.io.FileHasher
import com.malinskiy.marathon.io.FileManager
import com.malinskiy.marathon.io.Md5FileHasher
import com.malinskiy.marathon.json.FileSerializer
import com.malinskiy.marathon.time.SystemTimer
import com.malinskiy.marathon.time.Timer
import org.koin.core.KoinApplication
import org.koin.core.context.startKoin
import org.koin.core.definition.DefinitionFactory
import org.koin.dsl.koinApplication
import org.koin.dsl.module
import java.io.File
import java.time.Clock
Expand Down Expand Up @@ -68,20 +68,19 @@ fun coreModule(timer: Timer?) = module {
single<Timer> { timer ?: SystemTimer(get()) }
single<ProgressReporter> { ProgressReporter(get()) }
single<StrictRunChecker> { ConfigurationStrictRunChecker(get()) }
single<Marathon> { Marathon(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get()) }
single<Marathon> { Marathon(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get()) }
}

fun KoinApplication.marathonConfiguration(configuration: Configuration): KoinApplication {
koin.rootScope.beanRegistry.saveDefinition(DefinitionFactory.createSingle { configuration })
return this
}

fun marathonStartKoin(configuration: Configuration, timer: Timer? = null): KoinApplication {
return startKoin {
fun marathonStartKoin(configuration: Configuration, timer: Timer? = null): KoinApplication =
koinApplication {
marathonConfiguration(configuration)
modules(timer?.let { coreModule(timer) } ?: coreModule)
modules(cacheModule)
modules(analyticsModule)
modules(configuration.vendorConfiguration.modules())
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,10 @@
package com.malinskiy.marathon.vendor

import com.malinskiy.marathon.cache.test.key.ComponentCacheKeyProvider
import com.malinskiy.marathon.device.DeviceFeature
import com.malinskiy.marathon.device.DeviceProvider
import com.malinskiy.marathon.execution.ComponentInfoExtractor
import com.malinskiy.marathon.execution.TestParser
import com.malinskiy.marathon.log.MarathonLogConfigurator
import org.koin.core.module.Module

interface VendorConfiguration {
fun logConfigurator(): MarathonLogConfigurator?
fun testParser(): TestParser?
fun deviceProvider(): DeviceProvider?
fun preferableRecorderType(): DeviceFeature?
fun componentInfoExtractor(): ComponentInfoExtractor?
fun componentCacheKeyProvider(): ComponentCacheKeyProvider?

fun modules(): List<Module> = emptyList()
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import com.malinskiy.marathon.test.setupMarathon
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runTest
import org.amshove.kluent.shouldBe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import com.malinskiy.marathon.time.Timer
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runTest
import org.amshove.kluent.mock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import com.malinskiy.marathon.test.setupMarathon
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runTest
import org.amshove.kluent.shouldBe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import com.malinskiy.marathon.time.Timer
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runTest
import org.amshove.kluent.mock
Expand Down
27 changes: 0 additions & 27 deletions core/src/test/kotlin/com/malinskiy/marathon/spek/DeclareMock.kt

This file was deleted.

41 changes: 0 additions & 41 deletions core/src/test/kotlin/com/malinskiy/marathon/spek/KoinSpek.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.malinskiy.marathon.worker

import com.malinskiy.marathon.Marathon
import com.malinskiy.marathon.MarathonRunner
import com.malinskiy.marathon.di.marathonStartKoin
import com.malinskiy.marathon.execution.ComponentInfo
import com.malinskiy.marathon.execution.Configuration
Expand All @@ -17,25 +16,27 @@ class WorkerRunnable(

private val log = MarathonLogging.logger {}

private lateinit var marathon: MarathonRunner

override fun run() = runBlocking {
log.debug("Starting Marathon worker")

val application = marathonStartKoin(configuration)
marathon = application.koin.get<Marathon>()
marathon.start()

for (component in componentsChannel) {
log.debug("Scheduling tests for $component")
marathon.scheduleTests(component)
try {
val marathon = application.koin.get<Marathon>()
marathon.start()

for (component in componentsChannel) {
log.debug("Scheduling tests for $component")
marathon.scheduleTests(component)
}

log.debug("Waiting for completion")
stopAndWaitForCompletion(marathon)
} finally {
application.close()
}

log.debug("Waiting for completion")
stopAndWaitForCompletion()
}

private suspend fun stopAndWaitForCompletion() {
private suspend fun stopAndWaitForCompletion(marathon: Marathon) {
val success = marathon.stopAndWaitForCompletion()

val shouldReportFailure = !configuration.ignoreFailures
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,8 @@ package com.malinskiy.marathon.android

import com.malinskiy.marathon.android.di.androidModule
import com.malinskiy.marathon.android.serial.SerialStrategy
import com.malinskiy.marathon.cache.test.key.ComponentCacheKeyProvider
import com.malinskiy.marathon.device.DeviceFeature
import com.malinskiy.marathon.device.DeviceProvider
import com.malinskiy.marathon.execution.ComponentInfoExtractor
import com.malinskiy.marathon.execution.TestParser
import com.malinskiy.marathon.log.MarathonLogConfigurator
import com.malinskiy.marathon.vendor.VendorConfiguration
import org.koin.core.KoinComponent
import org.koin.core.get
import org.koin.core.module.Module
import java.io.File

Expand All @@ -34,20 +27,10 @@ data class AndroidConfiguration(
val installOptions: String = DEFAULT_INSTALL_OPTIONS,
val preferableRecorderType: DeviceFeature? = null,
val serialStrategy: SerialStrategy = SerialStrategy.AUTOMATIC
) : VendorConfiguration, KoinComponent {
) : VendorConfiguration {

private val koinModules = listOf(androidModule) + implementationModules

override fun testParser(): TestParser? = get()

override fun componentInfoExtractor(): ComponentInfoExtractor? = get()

override fun componentCacheKeyProvider(): ComponentCacheKeyProvider? = get()

override fun deviceProvider(): DeviceProvider? = get()

override fun logConfigurator(): MarathonLogConfigurator = AndroidLogConfigurator()

override fun preferableRecorderType(): DeviceFeature? = preferableRecorderType

override fun modules() = koinModules
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.malinskiy.marathon.android.di

import com.malinskiy.marathon.android.AndroidComponentCacheKeyProvider
import com.malinskiy.marathon.android.AndroidComponentInfoExtractor
import com.malinskiy.marathon.android.AndroidLogConfigurator
import com.malinskiy.marathon.android.AndroidTestParser
import com.malinskiy.marathon.android.ApkFileHasher
import com.malinskiy.marathon.android.executor.logcat.LogcatCollector
Expand All @@ -12,6 +13,7 @@ import com.malinskiy.marathon.cache.test.key.ComponentCacheKeyProvider
import com.malinskiy.marathon.execution.ComponentInfoExtractor
import com.malinskiy.marathon.execution.TestParser
import com.malinskiy.marathon.io.CachedFileHasher
import com.malinskiy.marathon.log.MarathonLogConfigurator
import com.malinskiy.marathon.report.logs.LogsProvider
import org.koin.dsl.module

Expand All @@ -23,4 +25,5 @@ val androidModule = module {
single<LogcatEventsListener?> { get<LogcatCollector>() }
single<LogsProvider?> { get<LogcatCollector>() }
single<LogcatListener?> { LogcatEventsAdapter(get()) }
single<MarathonLogConfigurator?> { AndroidLogConfigurator() }
}
Loading

0 comments on commit 7976ff2

Please sign in to comment.