From 1d202a7311bc6cdca92356c70f64b857b641956a Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 13 Jan 2020 10:15:01 +0600 Subject: [PATCH] asFlow extension --- CHANGELOG.md | 2 ++ build.gradle | 1 + .../krontab/utils/SchedulerFlow.kt | 25 ++++++++++++++ .../insanusmokrassar/krontab/utils/RunTest.kt | 8 +++++ .../krontab/utils/SchedulerFlow.kt | 34 +++++++++++++++++++ .../insanusmokrassar/krontab/utils/RunTest.kt | 5 +++ .../insanusmokrassar/krontab/utils/RunTest.kt | 9 +++++ 7 files changed, 84 insertions(+) create mode 100644 src/commonMain/kotlin/com/insanusmokrassar/krontab/utils/SchedulerFlow.kt create mode 100644 src/commonTest/kotlin/com/insanusmokrassar/krontab/utils/RunTest.kt create mode 100644 src/commonTest/kotlin/com/insanusmokrassar/krontab/utils/SchedulerFlow.kt create mode 100644 src/jsTest/kotlin/com/insanusmokrassar/krontab/utils/RunTest.kt create mode 100644 src/jvmTest/kotlin/com/insanusmokrassar/krontab/utils/RunTest.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index fe02d12..8dc3acf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,3 +8,5 @@ * Klock `1.7.3` -> `1.8.6` ## 0.2.1 + +* Added support of flows: now any `KronScheduler` can be convert to `Flow` using `asFlow` extension diff --git a/build.gradle b/build.gradle index 42e081f..1edeb16 100644 --- a/build.gradle +++ b/build.gradle @@ -47,6 +47,7 @@ kotlin { implementation kotlin('test-common') implementation kotlin('test-annotations-common') implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlin_coroutines_version" } } jvmMain { diff --git a/src/commonMain/kotlin/com/insanusmokrassar/krontab/utils/SchedulerFlow.kt b/src/commonMain/kotlin/com/insanusmokrassar/krontab/utils/SchedulerFlow.kt new file mode 100644 index 0000000..bf0c0f8 --- /dev/null +++ b/src/commonMain/kotlin/com/insanusmokrassar/krontab/utils/SchedulerFlow.kt @@ -0,0 +1,25 @@ +package com.insanusmokrassar.krontab.utils + +import com.insanusmokrassar.krontab.KronScheduler +import com.soywiz.klock.DateTime +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* + +@FlowPreview +fun KronScheduler.asFlow(): Flow = SchedulerFlow(this) + +@FlowPreview +class SchedulerFlow( + private val scheduler: KronScheduler +) : AbstractFlow() { + @FlowPreview + override suspend fun collectSafely(collector: FlowCollector) { + while (true) { + val now = DateTime.now() + val nextTime = scheduler.next(now) + val sleepDelay = (nextTime - now).millisecondsLong + delay(sleepDelay) + collector.emit(nextTime) + } + } +} \ No newline at end of file diff --git a/src/commonTest/kotlin/com/insanusmokrassar/krontab/utils/RunTest.kt b/src/commonTest/kotlin/com/insanusmokrassar/krontab/utils/RunTest.kt new file mode 100644 index 0000000..129a4b5 --- /dev/null +++ b/src/commonTest/kotlin/com/insanusmokrassar/krontab/utils/RunTest.kt @@ -0,0 +1,8 @@ +package com.insanusmokrassar.krontab.utils + +import kotlinx.coroutines.CoroutineScope + +/** + * Workaround to use suspending functions in unit tests + */ +expect fun runTest(block: suspend (scope : CoroutineScope) -> Unit) diff --git a/src/commonTest/kotlin/com/insanusmokrassar/krontab/utils/SchedulerFlow.kt b/src/commonTest/kotlin/com/insanusmokrassar/krontab/utils/SchedulerFlow.kt new file mode 100644 index 0000000..29eca3b --- /dev/null +++ b/src/commonTest/kotlin/com/insanusmokrassar/krontab/utils/SchedulerFlow.kt @@ -0,0 +1,34 @@ +package com.insanusmokrassar.krontab.utils + +import com.insanusmokrassar.krontab.builder.buildSchedule +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.takeWhile +import kotlin.test.Test +import kotlin.test.assertEquals + +@ExperimentalCoroutinesApi +@FlowPreview +class SchedulerFlowTests { + @Test + fun testThatFlowIsCorrectlyWorkEverySecond() { + val kronScheduler = buildSchedule { + seconds { + 0 every 1 + } + } + + val flow = kronScheduler.asFlow() + + runTest { + val mustBeCollected = 10 + var collected = 0 + flow.takeWhile { + collected < mustBeCollected + }.collect { + collected++ + } + assertEquals(mustBeCollected, collected) + } + } +} diff --git a/src/jsTest/kotlin/com/insanusmokrassar/krontab/utils/RunTest.kt b/src/jsTest/kotlin/com/insanusmokrassar/krontab/utils/RunTest.kt new file mode 100644 index 0000000..5d87632 --- /dev/null +++ b/src/jsTest/kotlin/com/insanusmokrassar/krontab/utils/RunTest.kt @@ -0,0 +1,5 @@ +package com.insanusmokrassar.krontab.utils + +import kotlinx.coroutines.* + +actual fun runTest(block: suspend (scope : CoroutineScope) -> Unit): dynamic = GlobalScope.promise { block(this) } diff --git a/src/jvmTest/kotlin/com/insanusmokrassar/krontab/utils/RunTest.kt b/src/jvmTest/kotlin/com/insanusmokrassar/krontab/utils/RunTest.kt new file mode 100644 index 0000000..a20cefc --- /dev/null +++ b/src/jvmTest/kotlin/com/insanusmokrassar/krontab/utils/RunTest.kt @@ -0,0 +1,9 @@ +package com.insanusmokrassar.krontab.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.runBlocking + +/** + * Workaround to use suspending functions in unit tests + */ +actual fun runTest(block: suspend (scope: CoroutineScope) -> Unit) = runBlocking(block = block)