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

Commit 1bbbc897 authored by Lucas Silva's avatar Lucas Silva
Browse files

Ensure boolean flow helpers only emit when value changes

Currently these helpers are emitting each time the underlying flows
emit, even if the value doesn't change.

Bug: 333774684
Test: atest BooleanFlowOperatorsTest
Flag: N/A
Change-Id: I10d713373c7f05d856cf1462796c30b1e406ff36
parent 8fecf6ff
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
import com.android.systemui.util.kotlin.BooleanFlowOperators.and
@@ -27,6 +28,7 @@ import com.android.systemui.util.kotlin.BooleanFlowOperators.not
import com.android.systemui.util.kotlin.BooleanFlowOperators.or
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import org.junit.Test
@@ -61,6 +63,21 @@ class BooleanFlowOperatorsTest : SysuiTestCase() {
            assertThat(result).isFalse()
        }

    @Test
    fun and_onlyEmitsWhenValueChanges() =
        testScope.runTest {
            val flow1 = MutableStateFlow(false)
            val flow2 = MutableStateFlow(false)
            val values by collectValues(and(flow1, flow2))

            assertThat(values).containsExactly(false)
            flow1.value = true
            // Overall value is still false, we should not have emitted again.
            assertThat(values).containsExactly(false)
            flow2.value = true
            assertThat(values).containsExactly(false, true).inOrder()
        }

    @Test
    fun or_allTrue_returnsTrue() =
        testScope.runTest {
@@ -82,6 +99,20 @@ class BooleanFlowOperatorsTest : SysuiTestCase() {
            assertThat(result).isFalse()
        }

    @Test
    fun or_onlyEmitsWhenValueChanges() =
        testScope.runTest {
            val flow1 = MutableStateFlow(false)
            val flow2 = MutableStateFlow(false)
            val values by collectValues(or(flow1, flow2))

            assertThat(values).containsExactly(false)
            flow1.value = true
            assertThat(values).containsExactly(false, true).inOrder()
            flow2.value = true
            assertThat(values).containsExactly(false, true).inOrder()
        }

    @Test
    fun not_true_returnsFalse() =
        testScope.runTest {
+3 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.systemui.util.kotlin

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map

object BooleanFlowOperators {
@@ -31,7 +32,7 @@ object BooleanFlowOperators {
     * ```
     */
    fun and(vararg flows: Flow<Boolean>): Flow<Boolean> =
        combine(flows.asIterable()) { values -> values.all { it } }
        combine(flows.asIterable()) { values -> values.all { it } }.distinctUntilChanged()

    /**
     * Logical NOT operator for a boolean flow.
@@ -48,5 +49,5 @@ object BooleanFlowOperators {
     * determine the result.
     */
    fun or(vararg flows: Flow<Boolean>): Flow<Boolean> =
        combine(flows.asIterable()) { values -> values.any { it } }
        combine(flows.asIterable()) { values -> values.any { it } }.distinctUntilChanged()
}