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

Commit d908c97a authored by Lucas Silva's avatar Lucas Silva Committed by Automerger Merge Worker
Browse files

Merge "Add helper to convert a kotlin flow to a Condition" into udc-dev am: 6a84c0a5

parents abe905c4 6a84c0a5
Loading
Loading
Loading
Loading
+23 −0
Original line number Original line Diff line number Diff line
package com.android.systemui.shared.condition

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch

/** Converts a boolean flow to a [Condition] object which can be used with a [Monitor] */
@JvmOverloads
fun Flow<Boolean>.toCondition(scope: CoroutineScope, initialValue: Boolean? = null): Condition {
    return object : Condition(initialValue, false) {
        var job: Job? = null

        override fun start() {
            job = scope.launch { collect { updateCondition(it) } }
        }

        override fun stop() {
            job?.cancel()
            job = null
        }
    }
}
+135 −0
Original line number Original line Diff line number Diff line
package com.android.systemui.shared.condition

import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith

@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidTestingRunner::class)
class ConditionExtensionsTest : SysuiTestCase() {
    private lateinit var testScope: TestScope

    @Before
    fun setUp() {
        testScope = TestScope(StandardTestDispatcher())
    }

    @Test
    fun flowInitiallyTrue() =
        testScope.runTest {
            val flow = flowOf(true)
            val condition = flow.toCondition(this)

            runCurrent()
            assertThat(condition.isConditionSet).isFalse()

            condition.start()
            runCurrent()
            assertThat(condition.isConditionSet).isTrue()
            assertThat(condition.isConditionMet).isTrue()
        }

    @Test
    fun flowInitiallyFalse() =
        testScope.runTest {
            val flow = flowOf(false)
            val condition = flow.toCondition(this)

            runCurrent()
            assertThat(condition.isConditionSet).isFalse()

            condition.start()
            runCurrent()
            assertThat(condition.isConditionSet).isTrue()
            assertThat(condition.isConditionMet).isFalse()
        }

    @Test
    fun emptyFlowWithNoInitialValue() =
        testScope.runTest {
            val flow = emptyFlow<Boolean>()
            val condition = flow.toCondition(this)
            condition.start()

            runCurrent()
            assertThat(condition.isConditionSet).isFalse()
            assertThat(condition.isConditionMet).isFalse()
        }

    @Test
    fun emptyFlowWithInitialValueOfTrue() =
        testScope.runTest {
            val flow = emptyFlow<Boolean>()
            val condition = flow.toCondition(scope = this, initialValue = true)
            condition.start()

            runCurrent()
            assertThat(condition.isConditionSet).isTrue()
            assertThat(condition.isConditionMet).isTrue()
        }

    @Test
    fun emptyFlowWithInitialValueOfFalse() =
        testScope.runTest {
            val flow = emptyFlow<Boolean>()
            val condition = flow.toCondition(scope = this, initialValue = false)
            condition.start()

            runCurrent()
            assertThat(condition.isConditionSet).isTrue()
            assertThat(condition.isConditionMet).isFalse()
        }

    @Test
    fun conditionUpdatesWhenFlowEmitsNewValue() =
        testScope.runTest {
            val flow = MutableStateFlow(false)
            val condition = flow.toCondition(this)
            condition.start()

            runCurrent()
            assertThat(condition.isConditionSet).isTrue()
            assertThat(condition.isConditionMet).isFalse()

            flow.value = true
            runCurrent()
            assertThat(condition.isConditionMet).isTrue()

            flow.value = false
            runCurrent()
            assertThat(condition.isConditionMet).isFalse()

            condition.stop()
        }

    @Test
    fun stoppingConditionUnsubscribesFromFlow() =
        testScope.runTest {
            val flow = MutableSharedFlow<Boolean>()
            val condition = flow.toCondition(this)
            runCurrent()
            assertThat(flow.subscriptionCount.value).isEqualTo(0)

            condition.start()
            runCurrent()
            assertThat(flow.subscriptionCount.value).isEqualTo(1)

            condition.stop()
            runCurrent()
            assertThat(flow.subscriptionCount.value).isEqualTo(0)
        }
}