Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.instacart.formula.test

import com.instacart.formula.IFormula
import com.instacart.formula.RuntimeConfig
import com.instacart.formula.start
import com.instacart.formula.toFlow
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.DelicateCoroutinesApi
Expand All @@ -16,6 +17,7 @@ import kotlinx.coroutines.launch
class TestFormulaObserver<Input : Any, Output : Any, FormulaT : IFormula<Input, Output>>(
private val runtimeConfig: RuntimeConfig,
val formula: FormulaT,
private val isValidationEnabled: Boolean = true,
) {

private val values = mutableListOf<Output>()
Expand All @@ -31,7 +33,8 @@ class TestFormulaObserver<Input : Any, Output : Any, FormulaT : IFormula<Input,
context = Dispatchers.Unconfined,
start = CoroutineStart.UNDISPATCHED,
) {
formula.toFlow(inputFlow, runtimeConfig)
val flow = start(inputFlow, formula, runtimeConfig, isValidationEnabled)
flow
.catch { errors.add(it) }
.collect { values.add(it) }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.instacart.formula.test

import com.instacart.formula.Action
import com.instacart.formula.Formula
import com.instacart.formula.IFormula
import com.instacart.formula.RuntimeConfig
import com.instacart.formula.plugin.Dispatcher
Expand All @@ -9,12 +10,8 @@ import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.cancel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestCoroutineScheduler
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlin.coroutines.coroutineContext
Expand All @@ -23,19 +20,25 @@ import kotlin.coroutines.coroutineContext
* An extension function to create a [TestFormulaObserver] for a [IFormula] instance.
*
* Note: Formula won't start until you pass it an [input][TestFormulaObserver.input].
*
* @param isValidationEnabled A boolean that validates inputs and outputs by
* running [Formula.evaluate] twice.
*/
fun <Input : Any, Output : Any, F: IFormula<Input, Output>> F.test(
isValidationEnabled: Boolean = true,
inspector: Inspector? = null,
dispatcher: Dispatcher? = null,
): TestFormulaObserver<Input, Output, F> {
val runtimeConfig = RuntimeConfig(
isValidationEnabled = isValidationEnabled,
inspector = inspector,
defaultDispatcher = dispatcher,
)

return TestFormulaObserver(runtimeConfig, this)
return TestFormulaObserver(
runtimeConfig = runtimeConfig,
formula = this,
isValidationEnabled = isValidationEnabled,
)
}

suspend fun <Event> Action<Event>.test(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class FormulaRuntime<Input : Any, Output : Any>(
context = coroutineContext + SupervisorJob(parent = coroutineContext[Job])
)

private val isValidationEnabled = config.isValidationEnabled
private var isValidationEnabled = false
private val inspector = FormulaPlugins.inspector(
type = formula.type(),
local = config.inspector,
Expand Down Expand Up @@ -117,6 +117,10 @@ class FormulaRuntime<Input : Any, Output : Any>(
}
}

fun setValidationEnabled(enabled: Boolean) {
isValidationEnabled = enabled
}

private fun isKeyValid(input: Input): Boolean {
return this.input == null || key == formula.key(input)
}
Expand Down
4 changes: 0 additions & 4 deletions formula/src/main/java/com/instacart/formula/RuntimeConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,8 @@ import com.instacart.formula.plugin.Dispatcher
* @param defaultDispatcher Dispatcher used for event processing (this can be overwritten by
* individual events). By default, formula runs on the thread on which the event arrived on.
* @param inspector Inspector that will be used when configuring the formula.
* @param isValidationEnabled A boolean that validates inputs and outputs by
* running [Formula.evaluate] twice. Should NOT be used in production builds,
* preferably only unit tests.
*/
class RuntimeConfig(
val defaultDispatcher: Dispatcher? = null,
val inspector: Inspector? = null,
val isValidationEnabled: Boolean = false,
)
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,17 @@ fun <Input : Any, Output : Any> IFormula<Input, Output>.toFlow(
)
}

private fun <Input : Any, Output : Any> start(
fun <Input : Any, Output : Any> start(
input: Flow<Input>,
formula: IFormula<Input, Output>,
config: RuntimeConfig?,
isValidationEnabled: Boolean = false,
): Flow<Output> {
val callbackFlow = callbackFlow {
val runtime = formula.asRuntime(coroutineContext, config)
runtime.setOnOutput(this::trySend)
runtime.setOnError(this::close)
runtime.setValidationEnabled(isValidationEnabled)

launch {
input.collect(runtime::onInput)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@ import com.google.common.truth.Truth.assertThat
import org.junit.Test

class RuntimeConfigTest {
@Test
fun `validation is not enabled by default`() {
val config = RuntimeConfig()
assertThat(config.isValidationEnabled).isFalse()
}

@Test
fun `default dispatcher is null`() {
val config = RuntimeConfig()
Expand Down