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

Commit 862a7b01 authored by Nick Chameyev's avatar Nick Chameyev
Browse files

Fix flaky PhysicsBasedUnfoldTransitionProgressProviderTest

* Adds a wait condition to ensure that the progress has changed
  after sending hinge angle event
* Reduces minimum number of progress events for increasing/decreasing
  check
* Adjusts one scenario to not have increasing check as we can't
  guarantee number of progress events there

Bug: 348192890
Test: atest PhysicsBasedUnfoldTransitionProgressProviderTest
Flag: EXEMPT bugfix
Change-Id: Ie327d41f692d252d153e914c4cd481e04e6d3a7a
parent 3c6a0bab
Loading
Loading
Loading
Loading
+37 −16
Original line number Diff line number Diff line
@@ -29,10 +29,16 @@ import com.android.systemui.unfold.updates.FOLD_UPDATE_START_OPENING
import com.android.systemui.unfold.util.TestFoldStateProvider
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith

/**
 * This test class tests [PhysicsBasedUnfoldTransitionProgressProvider] in a more E2E
 * fashion, it uses real handler thread and timings, so it might be perceptible to more flakiness
 * compared to the other unit tests that do not perform real multithreaded interactions.
 */
@RunWith(AndroidJUnit4::class)
@SmallTest
class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
@@ -44,8 +50,8 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
        mock<UnfoldFrameCallbackScheduler.Factory>().apply {
            whenever(create()).then { UnfoldFrameCallbackScheduler() }
        }
    private val mockBgHandler = mock<Handler>()
    private val fakeHandler = Handler(HandlerThread("UnfoldBg").apply { start() }.looper)
    private val handlerThread = HandlerThread("UnfoldBg").apply { start() }
    private val bgHandler = Handler(handlerThread.looper)

    @Before
    fun setUp() {
@@ -54,20 +60,26 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
                context,
                schedulerFactory,
                foldStateProvider = foldStateProvider,
                progressHandler = fakeHandler
                progressHandler = bgHandler
            )
        progressProvider.addCallback(listener)
    }

    @After
    fun after() {
        handlerThread.quit()
    }

    @Test
    fun testUnfold_emitsIncreasingTransitionEvents() {
        runOnProgressThreadWithInterval(
            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
            { foldStateProvider.sendHingeAngleUpdate(10f) },
            { foldStateProvider.sendUnfoldedScreenAvailable() },
            { foldStateProvider.sendHingeAngleUpdate(90f) },
            { foldStateProvider.sendHingeAngleUpdate(180f) },
            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
            { foldStateProvider.sendUnfoldedScreenAvailable() }
        )
        sendHingeAngleAndEnsureAnimationUpdate(90f, 120f, 180f)
        runOnProgressThreadWithInterval(
            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) }
        )

        with(listener.ensureTransitionFinished()) {
@@ -91,7 +103,7 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
    }

    @Test
    fun testUnfold_screenAvailableOnlyAfterFullUnfold_emitsIncreasingTransitionEvents() {
    fun testUnfold_screenAvailableOnlyAfterFullUnfold_finishesWithUnfoldEvent() {
        runOnProgressThreadWithInterval(
            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
            { foldStateProvider.sendHingeAngleUpdate(10f) },
@@ -102,7 +114,6 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
        )

        with(listener.ensureTransitionFinished()) {
            assertIncreasingProgress()
            assertFinishedWithUnfold()
        }
    }
@@ -111,9 +122,9 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
    fun testFold_emitsDecreasingTransitionEvents() {
        runOnProgressThreadWithInterval(
            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_CLOSING) },
            { foldStateProvider.sendHingeAngleUpdate(170f) },
            { foldStateProvider.sendHingeAngleUpdate(90f) },
            { foldStateProvider.sendHingeAngleUpdate(10f) },
        )
        sendHingeAngleAndEnsureAnimationUpdate(170f, 90f, 10f)
        runOnProgressThreadWithInterval(
            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_CLOSED) },
        )

@@ -127,9 +138,9 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
    fun testUnfoldAndStopUnfolding_finishesTheUnfoldTransition() {
        runOnProgressThreadWithInterval(
            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
            { foldStateProvider.sendUnfoldedScreenAvailable() },
            { foldStateProvider.sendHingeAngleUpdate(10f) },
            { foldStateProvider.sendHingeAngleUpdate(90f) },
            { foldStateProvider.sendUnfoldedScreenAvailable() })
        sendHingeAngleAndEnsureAnimationUpdate(10f, 50f, 90f)
        runOnProgressThreadWithInterval(
            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN) },
        )

@@ -159,12 +170,22 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
        with(listener.ensureTransitionFinished()) { assertHasFoldAnimationAtTheEnd() }
    }

    private fun sendHingeAngleAndEnsureAnimationUpdate(vararg angles: Float) {
        angles.forEach { angle ->
            listener.waitForProgressChangeAfter {
                bgHandler.post {
                    foldStateProvider.sendHingeAngleUpdate(angle)
                }
            }
        }
    }

    private fun runOnProgressThreadWithInterval(
        vararg blocks: () -> Unit,
        intervalMillis: Long = 60,
    ) {
        blocks.forEach {
            fakeHandler.post(it)
            bgHandler.post(it)
            Thread.sleep(intervalMillis)
        }
    }
+20 −2
Original line number Diff line number Diff line
@@ -68,6 +68,24 @@ class TestUnfoldProgressListener : UnfoldTransitionProgressProvider.TransitionPr
        return recordings.first()
    }

    /**
     * Number of progress event for the currently running transition
     * Returns null if there is no currently running transition
     */
    val currentTransitionProgressEventCount: Int?
        get() = currentRecording?.progressHistory?.size

    /**
     * Runs [block] and ensures that there was at least once onTransitionProgress event after that
     */
    fun waitForProgressChangeAfter(block: () -> Unit) {
        val eventCount = currentTransitionProgressEventCount
        block()
        waitForCondition {
            currentTransitionProgressEventCount != eventCount
        }
    }

    fun assertStarted() {
        assertWithMessage("Transition didn't start").that(currentRecording).isNotNull()
    }
@@ -86,7 +104,7 @@ class TestUnfoldProgressListener : UnfoldTransitionProgressProvider.TransitionPr
    }

    class UnfoldTransitionRecording {
        private val progressHistory: MutableList<Float> = arrayListOf()
        val progressHistory: MutableList<Float> = arrayListOf()
        private var finishingInvocations: Int = 0

        fun addProgress(progress: Float) {
@@ -142,6 +160,6 @@ class TestUnfoldProgressListener : UnfoldTransitionProgressProvider.TransitionPr
    }

    private companion object {
        private const val MIN_ANIMATION_EVENTS = 5
        private const val MIN_ANIMATION_EVENTS = 3
    }
}