diff --git a/core/src/integrationTest/kotlin/com/malinskiy/marathon/scenario/CacheScenarios.kt b/core/src/integrationTest/kotlin/com/malinskiy/marathon/scenario/CacheScenarios.kt index 3acfa7d51..c3a350906 100644 --- a/core/src/integrationTest/kotlin/com/malinskiy/marathon/scenario/CacheScenarios.kt +++ b/core/src/integrationTest/kotlin/com/malinskiy/marathon/scenario/CacheScenarios.kt @@ -66,6 +66,21 @@ class CacheScenarios { assertTrue(isFromCache) } + @Test + fun `GIVEN cache is enabled and push is disabled WHEN running tests second time THEN test results are not from cache`() = runTest { + val test = createTest() + val cacheConfiguration = CacheConfiguration(remote = RemoteCacheConfiguration.Enabled(url = container.cacheUrl, push = false)) + + val build1OutputDir = tempDir.resolve("build-1") + runMarathonWithOneTest(cacheConfiguration, build1OutputDir, test) + + val build2OutputDir = tempDir.resolve("build-2") + runMarathonWithOneTest(cacheConfiguration, build2OutputDir, test) + + val isFromCache = isFromCache(build2OutputDir, test) + assertFalse(isFromCache) + } + private fun createTest(): MarathonTest = MarathonTest( pkg = "test", diff --git a/core/src/main/kotlin/com/malinskiy/marathon/analytics/TrackerFactory.kt b/core/src/main/kotlin/com/malinskiy/marathon/analytics/TrackerFactory.kt index 68437676b..6c056c705 100644 --- a/core/src/main/kotlin/com/malinskiy/marathon/analytics/TrackerFactory.kt +++ b/core/src/main/kotlin/com/malinskiy/marathon/analytics/TrackerFactory.kt @@ -47,7 +47,9 @@ internal class TrackerFactory( val mappingTracker = MappingTracker(delegatingTrackerInternal) track + mappingTracker - track + cacheTestResultsTracker + if (configuration.cache.isPushEnabled) { + track + cacheTestResultsTracker + } configuration.analyticsTracker?.let { track + it } return delegatingTrackerInternal diff --git a/core/src/main/kotlin/com/malinskiy/marathon/cache/config/RemoteCacheConfiguration.kt b/core/src/main/kotlin/com/malinskiy/marathon/cache/config/RemoteCacheConfiguration.kt index d41d917b2..bf80e45f9 100644 --- a/core/src/main/kotlin/com/malinskiy/marathon/cache/config/RemoteCacheConfiguration.kt +++ b/core/src/main/kotlin/com/malinskiy/marathon/cache/config/RemoteCacheConfiguration.kt @@ -6,7 +6,8 @@ sealed class RemoteCacheConfiguration { data class Enabled( val url: URI, - val credentials: Credentials? = null + val credentials: Credentials? = null, + val push: Boolean = true ) : RemoteCacheConfiguration() data object Disabled : RemoteCacheConfiguration() diff --git a/core/src/main/kotlin/com/malinskiy/marathon/execution/CacheConfiguration.kt b/core/src/main/kotlin/com/malinskiy/marathon/execution/CacheConfiguration.kt index da1d84803..594adeb8a 100644 --- a/core/src/main/kotlin/com/malinskiy/marathon/execution/CacheConfiguration.kt +++ b/core/src/main/kotlin/com/malinskiy/marathon/execution/CacheConfiguration.kt @@ -3,12 +3,13 @@ package com.malinskiy.marathon.execution import com.malinskiy.marathon.cache.config.LocalCacheConfiguration import com.malinskiy.marathon.cache.config.RemoteCacheConfiguration -// TODO: support optional cache push data class CacheConfiguration( val local: LocalCacheConfiguration = LocalCacheConfiguration.Disabled, val remote: RemoteCacheConfiguration = RemoteCacheConfiguration.Disabled ) { - val isEnabled: Boolean - get() = local !is LocalCacheConfiguration.Disabled || remote !is RemoteCacheConfiguration.Disabled + get() = local is LocalCacheConfiguration.Enabled || remote is RemoteCacheConfiguration.Enabled + + val isPushEnabled: Boolean + get() = remote is RemoteCacheConfiguration.Enabled && remote.push } diff --git a/core/src/main/kotlin/com/malinskiy/marathon/execution/Scheduler.kt b/core/src/main/kotlin/com/malinskiy/marathon/execution/Scheduler.kt index dfca9bb20..e6115dcb6 100644 --- a/core/src/main/kotlin/com/malinskiy/marathon/execution/Scheduler.kt +++ b/core/src/main/kotlin/com/malinskiy/marathon/execution/Scheduler.kt @@ -59,13 +59,8 @@ class Scheduler( private val scope = CoroutineScope(context) suspend fun initialize() { - logger.debug("Subscribing to devices") subscribeOnDevices() - - logger.debug("Initializing test cache") - subscribeToCacheController() - cacheLoader.initialize(scope) - cacheSaver.initialize(scope) + initializeCache() try { withTimeout(deviceProvider.deviceInitializationTimeoutMillis) { @@ -83,7 +78,9 @@ class Scheduler( @OptIn(DelicateCoroutinesApi::class) suspend fun stopAndWaitForCompletion() { - cacheLoader.stop() + if (configuration.cache.isEnabled) { + cacheLoader.stop() + } logger.debug("Requesting stop in pools") @@ -97,27 +94,45 @@ class Scheduler( child.join() } - cacheSaver.terminate() + if (configuration.cache.isPushEnabled) { + cacheSaver.terminate() + } } suspend fun addTests(shard: TestShard) { - pools.keys.forEach { pool -> - cacheLoader.addTests(pool, shard) + if (configuration.cache.isEnabled) { + pools.keys.forEach { pool -> + cacheLoader.addTests(pool, shard) + } + } else { + pools.values.forEach { + it.send(FromScheduler.AddTests(shard)) + } } } - private fun subscribeToCacheController() { - scope.launch { - for (cacheResult in cacheLoader.results) { - when (cacheResult) { - is CacheResult.Miss -> pools.getValue(cacheResult.pool).send(FromScheduler.AddTests(cacheResult.testShard)) - is CacheResult.Hit -> cachedTestsReporter.onCachedTest(cacheResult.pool, cacheResult.testResult) + private fun initializeCache() { + logger.debug("Test cache is ${if (configuration.cache.isEnabled) "enabled" else "disabled"}") + + if (configuration.cache.isEnabled) { + cacheLoader.initialize(scope) + scope.launch { + for (cacheResult in cacheLoader.results) { + when (cacheResult) { + is CacheResult.Miss -> pools.getValue(cacheResult.pool).send(FromScheduler.AddTests(cacheResult.testShard)) + is CacheResult.Hit -> cachedTestsReporter.onCachedTest(cacheResult.pool, cacheResult.testResult) + } } } } + if (configuration.cache.isPushEnabled) { + cacheSaver.initialize(scope) + } } private fun subscribeOnDevices() { + logger.debug("Subscribing to devices") + scope.launch { logger.debug("Reading messages from device provider") @@ -126,6 +141,7 @@ class Scheduler( is DeviceProvider.DeviceEvent.DeviceConnected -> { onDeviceConnected(msg, job, coroutineContext) } + is DeviceProvider.DeviceEvent.DeviceDisconnected -> { onDeviceDisconnected(msg) } diff --git a/marathon-gradle-plugin/src/main/kotlin/com/malinskiy/marathon/CachePluginConfiguration.kt b/marathon-gradle-plugin/src/main/kotlin/com/malinskiy/marathon/CachePluginConfiguration.kt index 562545617..3c9309b46 100644 --- a/marathon-gradle-plugin/src/main/kotlin/com/malinskiy/marathon/CachePluginConfiguration.kt +++ b/marathon-gradle-plugin/src/main/kotlin/com/malinskiy/marathon/CachePluginConfiguration.kt @@ -19,7 +19,6 @@ interface CachePluginConfiguration { val remote: RemoteCacheExtension fun local(action: Action) { - local.initDefaults() action.execute(local) } @@ -30,16 +29,22 @@ interface CachePluginConfiguration { interface LocalCacheExtension { val directory: DirectoryProperty + val enabled: Property val removeUnusedEntriesAfterDays: Property } interface RemoteCacheExtension { val url: Property val credentials: Property + val enabled: Property + val push: Property } -internal fun LocalCacheExtension.initDefaults() { - removeUnusedEntriesAfterDays.convention(7) +internal fun CachePluginConfiguration.initDefaults() { + local.enabled.convention(false) + local.removeUnusedEntriesAfterDays.convention(7) + remote.enabled.convention(false) + remote.push.convention(true) } internal fun CachePluginConfiguration.toCacheConfiguration(): CacheConfiguration = @@ -49,15 +54,19 @@ internal fun CachePluginConfiguration.toCacheConfiguration(): CacheConfiguration ) private fun LocalCacheExtension.toConfig(): LocalCacheConfiguration = - if (directory.isPresent) { + if (enabled.get()) { LocalCacheConfiguration.Enabled(directory.get().asFile, removeUnusedEntriesAfterDays.get()) } else { LocalCacheConfiguration.Disabled } private fun RemoteCacheExtension.toConfig(): RemoteCacheConfiguration = - if (url.isPresent) { - RemoteCacheConfiguration.Enabled(url.get(), credentials.orNull?.toCredentials()) + if (enabled.get()) { + RemoteCacheConfiguration.Enabled( + url = url.get(), + credentials = credentials.orNull?.toCredentials(), + push = push.get() + ) } else { RemoteCacheConfiguration.Disabled } diff --git a/marathon-gradle-plugin/src/main/kotlin/com/malinskiy/marathon/MarathonExtension.kt b/marathon-gradle-plugin/src/main/kotlin/com/malinskiy/marathon/MarathonExtension.kt index 700d314d9..b69ce93e1 100644 --- a/marathon-gradle-plugin/src/main/kotlin/com/malinskiy/marathon/MarathonExtension.kt +++ b/marathon-gradle-plugin/src/main/kotlin/com/malinskiy/marathon/MarathonExtension.kt @@ -112,6 +112,7 @@ interface MarathonExtension { } internal fun MarathonExtension.initDefaults() { + cache.initDefaults() poolingStrategy.initDefaults() strictRunConfiguration.initDefaults()