Skip to content

Commit

Permalink
Add test for events arriving on background thread.
Browse files Browse the repository at this point in the history
  • Loading branch information
Laimiux committed Jan 3, 2024
1 parent 62c935f commit d6e9101
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.instacart.formula.internal.FormulaManager
import com.instacart.formula.internal.FormulaManagerImpl
import com.instacart.formula.internal.ManagerDelegate
import com.instacart.formula.internal.ThreadChecker
import kotlinx.coroutines.Dispatchers
import java.util.LinkedList

/**
Expand Down Expand Up @@ -60,7 +61,13 @@ class FormulaRuntime<Input : Any, Output : Any>(
this.key = formula.key(input)

if (initialization) {
manager = FormulaManagerImpl(this, implementation, input, loggingType = formula::class, inspector = inspector)
manager = FormulaManagerImpl(
delegate = this,
formula = implementation,
initialInput = input,
loggingType = formula::class,
inspector = inspector,
)
run()

hasInitialFinished = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ internal class ChildrenManager(
val childFormulaHolder = children.findOrInit(key) {
val implementation = formula.implementation()
FormulaManagerImpl(
delegate,
implementation,
input,
delegate = delegate,
formula = implementation,
initialInput = input,
loggingType = formula::class,
inspector = inspector
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ internal class ListenerImpl<Input, State, EventT>(internal var key: Any) : Liste
// TODO: log if null listener (it might be due to formula removal or due to callback removal)
val manager = manager ?: return

val deferredTransition = DeferredTransition(this, transition, event)
val deferredTransition = DeferredTransition(this@ListenerImpl, transition, event)
manager.onPendingTransition(deferredTransition)
}

Expand Down
21 changes: 21 additions & 0 deletions formula/src/test/java/com/instacart/formula/FormulaRuntimeTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.instacart.formula
import com.google.common.truth.Truth
import com.google.common.truth.Truth.assertThat
import com.instacart.formula.actions.EmptyAction
import com.instacart.formula.actions.EventOnBgThreadAction
import com.instacart.formula.internal.ClearPluginsRule
import com.instacart.formula.internal.FormulaKey
import com.instacart.formula.internal.TestInspector
Expand Down Expand Up @@ -82,6 +83,7 @@ import org.junit.rules.RuleChain
import org.junit.rules.TestName
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import java.util.concurrent.TimeUnit
import kotlin.reflect.KClass

@RunWith(Parameterized::class)
Expand Down Expand Up @@ -631,6 +633,25 @@ class FormulaRuntimeTest(val runtime: TestableRuntime, val name: String) {
assertThat(eventCallback.values()).containsExactly("a", "b").inOrder()
}

@Test
fun `when action returns value on background thread, we emit an error`() {
val bgAction = EventOnBgThreadAction()
val eventCallback = TestEventCallback<String>()
val formula = OnlyUpdateFormula<Unit> {
bgAction.onEvent {
transition {
eventCallback(it.toString())
}
}
}

val observer = runtime.test(formula, Unit)
bgAction.latch.await(10, TimeUnit.MILLISECONDS)
assertThat(bgAction.errors.values().firstOrNull()?.message).contains(
"com.instacart.formula.subjects.OnlyUpdateFormula - Only thread that created it can post transition result Expected:"
)
}

@Test fun `stream is disposed when evaluation does not contain it`() {
DynamicStreamSubject(runtime)
.updateStreams(keys = arrayOf("1"))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.instacart.formula.actions

import com.instacart.formula.Action
import com.instacart.formula.Cancelable
import com.instacart.formula.test.TestEventCallback
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors

class EventOnBgThreadAction : Action<Int> {
val errors = TestEventCallback<Throwable>()
val latch = CountDownLatch(1)

override fun key(): Any? = null

override fun start(send: (Int) -> Unit): Cancelable? {
Executors.newSingleThreadExecutor().execute {
try {
send(0)
} catch (e: Throwable) {
errors.invoke(e)
} finally {
latch.countDown()
}
}
return null
}
}

0 comments on commit d6e9101

Please sign in to comment.