Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0628dfba authored by Alejandro Nijamkin's avatar Alejandro Nijamkin
Browse files

Adds Flow extension for collecting values into a list.

Usage is just:
val values by collectValues(underTest.flow)
assertThat(values).isEqualTo(listOf(expected1, expected2, ...))

Test: N/A
Bug: 274159734
Flag: N/A
Change-Id: I9f7ff736f9b7795c4bea91355bb2a42d00b6dfb5
parent 5f1f784b
Loading
Loading
Loading
Loading
+46 −9
Original line number Original line Diff line number Diff line
@@ -14,6 +14,8 @@
 * limitations under the License.
 * limitations under the License.
 */
 */


@file:Suppress("OPT_IN_USAGE")

package com.android.systemui.coroutines
package com.android.systemui.coroutines


import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.CoroutineContext
@@ -43,20 +45,55 @@ fun <T> TestScope.collectLastValue(
    context: CoroutineContext = EmptyCoroutineContext,
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    start: CoroutineStart = CoroutineStart.DEFAULT,
): FlowValue<T?> {
): FlowValue<T?> {
    var lastValue: T? = null
    val values by
    backgroundScope.launch(context, start) { flow.collect { lastValue = it } }
        collectValues(
    return FlowValueImpl {
            flow = flow,
            context = context,
            start = start,
        )
    return FlowValueImpl { values.lastOrNull() }
}

/**
 * Collect [flow] in a new [Job] and return a getter for the collection of values collected.
 *
 * ```
 * fun myTest() = runTest {
 *   // ...
 *   val values by collectValues(underTest.flow)
 *   assertThat(values).isEqualTo(listOf(expected1, expected2, ...))
 * }
 * ```
 */
fun <T> TestScope.collectValues(
    flow: Flow<T>,
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
): FlowValues<T> {
    val values = mutableListOf<T>()
    backgroundScope.launch(context, start) { flow.collect(values::add) }
    return FlowValuesImpl {
        runCurrent()
        runCurrent()
        lastValue
        values.toList()
    }
    }
}
}


/** @see collectLastValue */
/** @see collectLastValue */
interface FlowValue<T> : ReadOnlyProperty<Any?, T?> {
interface FlowValue<T> : ReadOnlyProperty<Any?, T> {
    operator fun invoke(): T?
    operator fun invoke(): T
}

/** @see collectValues */
interface FlowValues<T> : ReadOnlyProperty<Any?, List<T>> {
    operator fun invoke(): List<T>
}

private class FlowValueImpl<T>(private val block: () -> T) : FlowValue<T> {
    override operator fun invoke(): T = block()
    override fun getValue(thisRef: Any?, property: KProperty<*>): T = invoke()
}
}


private class FlowValueImpl<T>(private val block: () -> T?) : FlowValue<T> {
private class FlowValuesImpl<T>(private val block: () -> List<T>) : FlowValues<T> {
    override operator fun invoke(): T? = block()
    override operator fun invoke(): List<T> = block()
    override fun getValue(thisRef: Any?, property: KProperty<*>): T? = invoke()
    override fun getValue(thisRef: Any?, property: KProperty<*>): List<T> = invoke()
}
}