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

Commit 9a6792f2 authored by Lucas Silva's avatar Lucas Silva
Browse files

Modernize LowLightMonitorTest to follow best practices

Reduces use of mocking and removes old mockito usage for kotlin mockito.

Bug: 407633926
Test: atest LowLightMonitorTest
Flag: EXEMPT test update
Change-Id: If4a7b93bf4a637874ed809d69f3a39b6854e2335
parent 844c3ece
Loading
Loading
Loading
Loading
+66 −159
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@
package com.android.systemui.lowlightclock

import android.content.ComponentName
import android.content.pm.PackageManager
import android.content.packageManager
import android.testing.TestableLooper.RunWithLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -24,30 +24,25 @@ import com.android.dream.lowlight.LowLightDreamManager
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.domain.interactor.displayStateInteractor
import com.android.systemui.display.data.repository.displayRepository
import com.android.systemui.kosmos.runCurrent
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.backgroundScope
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.shared.condition.Condition
import com.android.systemui.shared.condition.Monitor
import com.android.systemui.testKosmos
import com.google.common.truth.Truth
import dagger.Lazy
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.asExecutor
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.clearInvocations
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever

@SmallTest
@RunWith(AndroidJUnit4::class)
@@ -55,217 +50,129 @@ import org.mockito.kotlin.whenever
class LowLightMonitorTest : SysuiTestCase() {
    val kosmos = testKosmos().useUnconfinedTestDispatcher()

    @Mock private lateinit var lowLightDreamManagerLazy: Lazy<LowLightDreamManager>
    private val Kosmos.lowLightDreamManager: LowLightDreamManager by
        Kosmos.Fixture { mock<LowLightDreamManager>() }

    @Mock private lateinit var lowLightDreamManager: LowLightDreamManager
    private val Kosmos.monitor: Monitor by Kosmos.Fixture { Monitor(testDispatcher.asExecutor()) }

    private val monitor: Monitor = prepareMonitor()
    private val Kosmos.logger: LowLightLogger by
        Kosmos.Fixture { LowLightLogger(logcatLogBuffer()) }

    @Mock private lateinit var logger: LowLightLogger
    private val Kosmos.condition: FakeCondition by
        Kosmos.Fixture { FakeCondition(scope = applicationCoroutineScope, initialValue = null) }

    private lateinit var lowLightMonitor: LowLightMonitor

    @Mock private lateinit var lazyConditions: Lazy<Set<Condition>>

    @Mock private lateinit var packageManager: PackageManager

    @Mock private lateinit var dreamComponent: ComponentName

    private val condition = mock<Condition>()

    private val conditionSet = setOf(condition)

    @Captor
    private lateinit var preconditionsSubscriptionCaptor: ArgumentCaptor<Monitor.Subscription>

    private fun prepareMonitor(): Monitor {
        val monitor = mock<Monitor>()
        whenever(monitor.addSubscription(ArgumentMatchers.any())).thenReturn(mock())

        return monitor
    }

    private fun setDisplayOn(screenOn: Boolean) {
        kosmos.displayRepository.setDefaultDisplayOff(!screenOn)
    }

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        whenever(lowLightDreamManagerLazy.get()).thenReturn(lowLightDreamManager)
        whenever(lazyConditions.get()).thenReturn(conditionSet)
        lowLightMonitor =
    private val Kosmos.underTest: LowLightMonitor by
        Kosmos.Fixture {
            LowLightMonitor(
                lowLightDreamManagerLazy,
                { lowLightDreamManager },
                monitor,
                lazyConditions,
                kosmos.displayStateInteractor,
                { setOf(condition) },
                displayStateInteractor,
                logger,
                dreamComponent,
                packageManager,
                kosmos.testScope.backgroundScope,
                backgroundScope,
            )
        whenever(monitor.addSubscription(ArgumentMatchers.any())).thenReturn(mock())
        val subscriptionCaptor = argumentCaptor<Monitor.Subscription>()

        setDisplayOn(false)
        }

        lowLightMonitor.start()
        verify(monitor).addSubscription(subscriptionCaptor.capture())
        clearInvocations(monitor)
    private var Kosmos.dreamComponent: ComponentName? by
        Kosmos.Fixture { ComponentName("test", "test.LowLightDream") }

        subscriptionCaptor.firstValue.callback.onConditionsChanged(true)
    private fun Kosmos.setDisplayOn(screenOn: Boolean) {
        displayRepository.setDefaultDisplayOff(!screenOn)
    }

    private fun getConditionCallback(monitor: Monitor): Monitor.Callback {
        val subscriptionCaptor = argumentCaptor<Monitor.Subscription>()
        verify(monitor).addSubscription(subscriptionCaptor.capture())
        return subscriptionCaptor.firstValue.callback
    @Before
    fun setUp() {
        kosmos.setDisplayOn(false)
    }

    @Test
    fun testSetAmbientLowLightWhenInLowLight() =
        kosmos.runTest {
            underTest.start()

            // Turn on screen
            setDisplayOn(true)

            // Set conditions to true
            val callback = getConditionCallback(monitor)
            callback.onConditionsChanged(true)
            condition.setValue(true)

            // Verify setting low light when condition is true
            Mockito.verify(lowLightDreamManager)
            verify(lowLightDreamManager)
                .setAmbientLightMode(LowLightDreamManager.AMBIENT_LIGHT_MODE_LOW_LIGHT)
        }

    @Test
    fun testExitAmbientLowLightWhenNotInLowLight() =
        kosmos.runTest {
            underTest.start()

            // Turn on screen
            setDisplayOn(true)

            // Set conditions to true then false
            val callback = getConditionCallback(monitor)
            callback.onConditionsChanged(true)
            condition.setValue(true)
            clearInvocations(lowLightDreamManager)
            callback.onConditionsChanged(false)
            condition.setValue(false)

            // Verify ambient light toggles back to light mode regular
            Mockito.verify(lowLightDreamManager)
            verify(lowLightDreamManager)
                .setAmbientLightMode(LowLightDreamManager.AMBIENT_LIGHT_MODE_REGULAR)
        }

    @Test
    fun testStopMonitorLowLightConditionsWhenScreenTurnsOff() =
        kosmos.runTest {
            val token = mock<Monitor.Subscription.Token>()
            whenever(monitor.addSubscription(ArgumentMatchers.any())).thenReturn(token)
            underTest.start()

            setDisplayOn(true)
            assertThat(condition.started).isTrue()

            // Verify removing subscription when screen turns off.
            setDisplayOn(false)
            Mockito.verify(monitor).removeSubscription(token)
        }

    @Test
    fun testSubscribeToLowLightConditionsOnlyOnceWhenScreenTurnsOn() =
        kosmos.runTest {
            val token = mock<Monitor.Subscription.Token>()
            whenever(monitor.addSubscription(ArgumentMatchers.any())).thenReturn(token)

            setDisplayOn(true)
            setDisplayOn(true)
            // Verify subscription is only added once.
            Mockito.verify(monitor, Mockito.times(1)).addSubscription(ArgumentMatchers.any())
        }

    @Test
    fun testSubscribedToExpectedConditions() =
        kosmos.runTest {
            val token = mock<Monitor.Subscription.Token>()
            whenever(monitor.addSubscription(ArgumentMatchers.any())).thenReturn(token)

            setDisplayOn(true)

            val conditions = captureConditions()
            // Verify Monitor is subscribed to the expected conditions
            Truth.assertThat(conditions).isEqualTo(conditionSet)
        }

    @Test
    fun testNotUnsubscribeIfNotSubscribedWhenScreenTurnsOff() =
        kosmos.runTest {
            setDisplayOn(true)
            clearInvocations(monitor)
            setDisplayOn(false)
            runCurrent()
            // Verify doesn't remove subscription since there is none.
            Mockito.verify(monitor).removeSubscription(ArgumentMatchers.any())
            assertThat(condition.started).isFalse()
        }

    @Test
    fun testSubscribeIfScreenIsOnWhenStarting() =
        kosmos.runTest {
            val monitor = prepareMonitor()

            setDisplayOn(true)

            val targetMonitor =
                LowLightMonitor(
                    lowLightDreamManagerLazy,
                    monitor,
                    lazyConditions,
                    displayStateInteractor,
                    logger,
                    dreamComponent,
                    packageManager,
                    testScope.backgroundScope,
                )

            // start
            targetMonitor.start()

            val callback = getConditionCallback(monitor)
            clearInvocations(monitor)
            callback.onConditionsChanged(true)

            // Verify to add subscription on start and when the screen state is on
            Mockito.verify(monitor).addSubscription(ArgumentMatchers.any())
            underTest.start()
            assertThat(condition.started).isTrue()
        }

    @Test
    fun testNoSubscribeIfDreamNotPresent() =
        kosmos.runTest {
            val monitor = prepareMonitor()

            setDisplayOn(true)
            dreamComponent = null

            val lowLightMonitor =
                LowLightMonitor(
                    lowLightDreamManagerLazy,
                    monitor,
                    lazyConditions,
                    displayStateInteractor,
                    logger,
                    null,
                    packageManager,
                    testScope,
                )

            // start
            lowLightMonitor.start()
            underTest.start()
            assertThat(condition.started).isFalse()
        }

            val callback = getConditionCallback(monitor)
            clearInvocations(monitor)
            callback.onConditionsChanged(true)
    private class FakeCondition(
        scope: CoroutineScope,
        initialValue: Boolean?,
        overriding: Boolean = false,
        @StartStrategy override val startStrategy: Int = START_EAGERLY,
    ) : Condition(scope, initialValue, overriding) {
        private var _started = false
        val started: Boolean
            get() = _started

        override suspend fun start() {
            _started = true
        }

            // Verify to add subscription on start and when the screen state is on
            Mockito.verify(monitor, never()).addSubscription(ArgumentMatchers.any())
        override fun stop() {
            _started = false
        }

    private fun captureConditions(): Set<Condition?> {
        Mockito.verify(monitor).addSubscription(preconditionsSubscriptionCaptor.capture())
        return preconditionsSubscriptionCaptor.value.conditions
        fun setValue(value: Boolean?) {
            value?.also { updateCondition(value) } ?: clearCondition()
        }
    }
}