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

Commit 35cca888 authored by Jiaming Cheng's avatar Jiaming Cheng
Browse files

[flexiglass] Fix WindowRootViewVisibilityInteractorTest failures with SceneContainerFlag

Adapted the logic correctly with `SceneContainerFlag`:
    - `isLockscreenOrShadeVisible_true()` and
       `isLockscreenOrShadeVisible_false()` now test various scene
       states (Idle and Transition).
    - `isLockscreenOrShadeVisible_matchesRepo()` is now annotated
        with `@DisableSceneContainer`.
    - `isLockscreenOrShadeVisibleAndInteractive_notVisible_false()`
       and `lockscreenShadeNotInteractive_statusBarServiceNotified()`
       now have conditional logic for flag-enabled and flag-disabled
       scenarios.

Also, this cl made WindowRootViewVisibilityInteractorTest
to a parameterized test with SceneContainerFlag.

Bug: 416716527
Flag: com.android.systemui.scene_container
Test: com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractorTest

Change-Id: I0d4a294488b47c06d5468bc073f7be9aaa55a822
parent 256cdd30
Loading
Loading
Loading
Loading
+337 −66
Original line number Diff line number Diff line
@@ -18,18 +18,28 @@ package com.android.systemui.scene.domain.interactor

import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import android.platform.test.flag.junit.FlagsParameterization
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.internal.statusbar.IStatusBarService
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.concurrency.fakeExecutor
import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.flags.andSceneContainer
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
import com.android.systemui.power.domain.interactor.PowerInteractorFactory
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.scene.data.repository.WindowRootViewVisibilityRepository
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.NotificationPresenter
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.data.repository.setActiveNotifs
@@ -42,64 +52,284 @@ import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
import org.mockito.kotlin.whenever
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
import platform.test.runner.parameterized.Parameters

@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWith(ParameterizedAndroidJunit4::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@android.platform.test.annotations.EnabledOnRavenwood
class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {
class WindowRootViewVisibilityInteractorTest(flags: FlagsParameterization) : SysuiTestCase() {

    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    private val testDispatcher = StandardTestDispatcher()
    private val iStatusBarService = mock<IStatusBarService>()
    private val executor = FakeExecutor(FakeSystemClock())
    private val windowRootViewVisibilityRepository =
        WindowRootViewVisibilityRepository(iStatusBarService, executor)
    private lateinit var executor: FakeExecutor
    private lateinit var windowRootViewVisibilityRepository: WindowRootViewVisibilityRepository
    private val keyguardRepository = FakeKeyguardRepository()
    private val headsUpManager = mock<HeadsUpManager>()
    private val notificationPresenter = mock<NotificationPresenter>()
    private val notificationsController = mock<NotificationsController>()
    private val powerInteractor = PowerInteractorFactory.create().powerInteractor
    private lateinit var powerInteractor: PowerInteractor
    private val activeNotificationsRepository = kosmos.activeNotificationListRepository
    private val activeNotificationsInteractor = kosmos.activeNotificationsInteractor
    private lateinit var underTest: WindowRootViewVisibilityInteractor

    companion object {
        @JvmStatic
        @Parameters(name = "{0}")
        fun getParams(): List<FlagsParameterization> {
            return FlagsParameterization.allCombinationsOf().andSceneContainer()
        }
    }

    init {
        mSetFlagsRule.setFlagsParameterization(flags)
    }

    @Before
    fun setUp() {
        executor = kosmos.fakeExecutor
        windowRootViewVisibilityRepository =
            WindowRootViewVisibilityRepository(iStatusBarService, executor)
        powerInteractor = kosmos.powerInteractor

    private val underTest =
        underTest =
            WindowRootViewVisibilityInteractor(
                    testScope.backgroundScope,
                    windowRootViewVisibilityRepository,
                    keyguardRepository,
                    headsUpManager,
                    powerInteractor,
                activeNotificationsInteractor,
                    kosmos.activeNotificationsInteractor,
                    kosmos::sceneInteractor,
                )
                .apply { setUp(notificationPresenter, notificationsController) }
    }

    @OptIn(ExperimentalCoroutinesApi::class)
    @Test
    fun isLockscreenOrShadeVisible_true() {
    fun isLockscreenOrShadeVisible_true() =
        kosmos.runTest {
            val actual by collectLastValue(underTest.isLockscreenOrShadeVisible)
            if (SceneContainerFlag.isEnabled) {
                // Idle: Current scene is Shade
                kosmos.sceneInteractor.setTransitionState(
                    flowOf(ObservableTransitionState.Idle(Scenes.Shade))
                )
                testScope.runCurrent()
                assertThat(actual).isTrue()

                // Idle: Current scene is Lockscreen
                kosmos.sceneInteractor.setTransitionState(
                    flowOf(ObservableTransitionState.Idle(Scenes.Lockscreen))
                )
                testScope.runCurrent()
                assertThat(actual).isTrue()

                // Idle: NotificationsShade overlay is present
                kosmos.sceneInteractor.setTransitionState(
                    flowOf(
                        ObservableTransitionState.Idle(
                            currentScene = Scenes.Gone,
                            currentOverlays = setOf(Overlays.NotificationsShade),
                        )
                    )
                )
                testScope.runCurrent()
                assertThat(actual).isTrue()

                // Idle: QuickSettingsShade overlay is present
                kosmos.sceneInteractor.setTransitionState(
                    flowOf(
                        ObservableTransitionState.Idle(
                            currentScene = Scenes.Gone,
                            currentOverlays = setOf(Overlays.QuickSettingsShade),
                        )
                    )
                )
                testScope.runCurrent()
                assertThat(actual).isTrue()

                // Test Transition States: To Shade
                val arbitraryProgress = flowOf(0.5f)
                val userInputOngoing = flowOf(true)

                kosmos.sceneInteractor.setTransitionState(
                    flowOf(
                        ObservableTransitionState.Transition(
                            fromScene = Scenes.Gone,
                            toScene = Scenes.Shade,
                            currentScene = flowOf(Scenes.Shade),
                            progress = arbitraryProgress,
                            isInitiatedByUserInput = true,
                            isUserInputOngoing = userInputOngoing,
                        )
                    )
                )
                testScope.runCurrent()
                assertThat(actual).isTrue()

                // Transition: From Shade
                kosmos.sceneInteractor.setTransitionState(
                    flowOf(
                        ObservableTransitionState.Transition(
                            fromScene = Scenes.Shade,
                            toScene = Scenes.Gone,
                            currentScene = flowOf(Scenes.Gone),
                            progress = arbitraryProgress,
                            isInitiatedByUserInput = true,
                            isUserInputOngoing = userInputOngoing,
                        )
                    )
                )
                testScope.runCurrent()
                assertThat(actual).isTrue()

                // Transition: To Lockscreen
                kosmos.sceneInteractor.setTransitionState(
                    flowOf(
                        ObservableTransitionState.Transition(
                            fromScene = Scenes.Gone,
                            toScene = Scenes.Lockscreen,
                            currentScene = flowOf(Scenes.Lockscreen),
                            progress = arbitraryProgress,
                            isInitiatedByUserInput = true,
                            isUserInputOngoing = userInputOngoing,
                        )
                    )
                )
                testScope.runCurrent()
                assertThat(actual).isTrue()

                // Transition: From Lockscreen
                kosmos.sceneInteractor.setTransitionState(
                    flowOf(
                        ObservableTransitionState.Transition(
                            fromScene = Scenes.Lockscreen,
                            toScene = Scenes.Gone,
                            currentScene = flowOf(Scenes.Gone),
                            progress = arbitraryProgress,
                            isInitiatedByUserInput = true,
                            isUserInputOngoing = userInputOngoing,
                        )
                    )
                )
                testScope.runCurrent()
                assertThat(actual).isTrue()

                // Transition: To NotificationsShade Overlay
                kosmos.sceneInteractor.setTransitionState(
                    flowOf(
                        ObservableTransitionState.Transition.showOverlay(
                            overlay = Overlays.NotificationsShade,
                            fromScene = Scenes.Gone,
                            currentOverlays = flowOf(setOf(Overlays.NotificationsShade)),
                            progress = arbitraryProgress,
                            isInitiatedByUserInput = true,
                            isUserInputOngoing = userInputOngoing,
                        )
                    )
                )
                testScope.runCurrent()
                assertThat(actual).isTrue()

                // Transition: From QuickSettingsShade Overlay
                kosmos.sceneInteractor.setTransitionState(
                    flowOf(
                        ObservableTransitionState.Transition.hideOverlay(
                            overlay = Overlays.QuickSettingsShade,
                            toScene = Scenes.Gone, // The scene to which we return
                            currentOverlays =
                                flowOf(emptySet()), // Overlays after this one is hidden
                            progress = arbitraryProgress,
                            isInitiatedByUserInput = true,
                            isUserInputOngoing = userInputOngoing,
                        )
                    )
                )
                testScope.runCurrent()
                assertThat(actual).isTrue()
            } else {
                underTest.setIsLockscreenOrShadeVisible(true)

        assertThat(underTest.isLockscreenOrShadeVisible.value).isTrue()
                assertThat(actual).isTrue()
            }
        }

    @OptIn(ExperimentalCoroutinesApi::class)
    @Test
    fun isLockscreenOrShadeVisible_false() {
    fun isLockscreenOrShadeVisible_false() =
        kosmos.runTest {
            val actual by collectLastValue(underTest.isLockscreenOrShadeVisible)
            if (SceneContainerFlag.isEnabled) {

                // Idle: Current scene is Gone
                kosmos.sceneInteractor.setTransitionState(
                    flowOf(ObservableTransitionState.Idle(Scenes.Gone))
                )
                testScope.runCurrent()
                assertThat(actual).isFalse()

                // Idle: Current scene is QuickSettings (not an overlay in this context)
                kosmos.sceneInteractor.setTransitionState(
                    flowOf(ObservableTransitionState.Idle(Scenes.QuickSettings))
                )
                testScope.runCurrent()
                assertThat(actual).isFalse()

                // Idle: Current scene is Communal
                kosmos.sceneInteractor.setTransitionState(
                    flowOf(ObservableTransitionState.Idle(Scenes.Communal))
                )
                testScope.runCurrent()
                assertThat(actual).isFalse()

                // Idle: Current scene is Dream
                kosmos.sceneInteractor.setTransitionState(
                    flowOf(ObservableTransitionState.Idle(Scenes.Dream))
                )
                testScope.runCurrent()
                assertThat(actual).isFalse()

                // Transition: To a scene that is not Lockscreen or Shade.
                val arbitraryProgress = flowOf(0.5f)
                val userInputOngoing = flowOf(true)

                kosmos.sceneInteractor.setTransitionState(
                    flowOf(
                        ObservableTransitionState.Transition(
                            fromScene = Scenes.Gone,
                            toScene = Scenes.Communal,
                            currentScene = flowOf(Scenes.Communal),
                            progress = arbitraryProgress,
                            isInitiatedByUserInput = true,
                            isUserInputOngoing = userInputOngoing,
                        )
                    )
                )
                testScope.runCurrent()
                assertThat(actual).isFalse()
            } else {
                underTest.setIsLockscreenOrShadeVisible(false)

        assertThat(underTest.isLockscreenOrShadeVisible.value).isFalse()
                assertThat(actual).isFalse()
            }
        }

    @Test
    @DisableSceneContainer
    // When SceneContainerFlag is enabled, setIsLockscreenOrShadeVisible directly
    // no longer controls the interactor's isLockscreenOrShadeVisible flow.
    fun isLockscreenOrShadeVisible_matchesRepo() {
        windowRootViewVisibilityRepository.setIsLockscreenOrShadeVisible(true)

@@ -110,20 +340,31 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {
        assertThat(underTest.isLockscreenOrShadeVisible.value).isFalse()
    }

    @OptIn(ExperimentalCoroutinesApi::class)
    @Test
    fun isLockscreenOrShadeVisibleAndInteractive_notVisible_false() =
        testScope.runTest {
        kosmos.runTest {
            val actual by collectLastValue(underTest.isLockscreenOrShadeVisibleAndInteractive)
            powerInteractor.setAwakeForTest()

            if (SceneContainerFlag.isEnabled) {
                // When SceneContainerFlag is enabled, setIsLockscreenOrShadeVisible directly
                // no longer controls the interactor's isLockscreenOrShadeVisible flow.
                // Instead, we change the scene to one that results in isLockscreenOrShadeVisible
                // being false.
                kosmos.sceneInteractor.setTransitionState(
                    flowOf(ObservableTransitionState.Idle(Scenes.Gone))
                )
                testScope.runCurrent()
            } else {
                underTest.setIsLockscreenOrShadeVisible(false)

            }
            assertThat(actual).isFalse()
        }

    @Test
    fun isLockscreenOrShadeVisibleAndInteractive_deviceAsleep_false() =
        testScope.runTest {
        kosmos.runTest {
            val actual by collectLastValue(underTest.isLockscreenOrShadeVisibleAndInteractive)
            underTest.setIsLockscreenOrShadeVisible(true)

@@ -134,7 +375,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {

    @Test
    fun isLockscreenOrShadeVisibleAndInteractive_visibleAndAwake_true() =
        testScope.runTest {
        kosmos.runTest {
            val actual by collectLastValue(underTest.isLockscreenOrShadeVisibleAndInteractive)

            underTest.setIsLockscreenOrShadeVisible(true)
@@ -145,7 +386,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {

    @Test
    fun isLockscreenOrShadeVisibleAndInteractive_visibleAndStartingToWake_true() =
        testScope.runTest {
        kosmos.runTest {
            val actual by collectLastValue(underTest.isLockscreenOrShadeVisibleAndInteractive)

            underTest.setIsLockscreenOrShadeVisible(true)
@@ -156,7 +397,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {

    @Test
    fun isLockscreenOrShadeVisibleAndStartingToSleep_false() =
        testScope.runTest {
        kosmos.runTest {
            val actual by collectLastValue(underTest.isLockscreenOrShadeVisibleAndInteractive)

            underTest.setIsLockscreenOrShadeVisible(true)
@@ -165,9 +406,10 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {
            assertThat(actual).isFalse()
        }

    @OptIn(ExperimentalCoroutinesApi::class)
    @Test
    fun lockscreenShadeInteractive_statusBarServiceNotified() =
        testScope.runTest {
        kosmos.runTest {
            underTest.start()

            makeLockscreenShadeVisible()
@@ -177,11 +419,32 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {
            verify(iStatusBarService).onPanelRevealed(any(), any())
        }

    @OptIn(ExperimentalCoroutinesApi::class)
    @Test
    fun lockscreenShadeNotInteractive_statusBarServiceNotified() =
        testScope.runTest {
        kosmos.runTest {
            underTest.start()
            testScope.runCurrent()

            if (SceneContainerFlag.isEnabled) {
                // Lockscreen/Shade is visible and interactive
                kosmos.sceneInteractor.setTransitionState(
                    flowOf(ObservableTransitionState.Idle(Scenes.Lockscreen))
                )
                testScope.runCurrent()
                powerInteractor.setAwakeForTest()
                testScope.runCurrent()
                executor.runAllReady()

                reset(iStatusBarService)

                // Make the lockscreen/shade "not interactive".
                kosmos.sceneInteractor.setTransitionState(
                    flowOf(ObservableTransitionState.Idle(Scenes.Gone))
                )
                testScope.runCurrent()
                executor.runAllReady()
            } else {
                // First, make the shade visible
                makeLockscreenShadeVisible()
                testScope.runCurrent()
@@ -191,6 +454,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {
                underTest.setIsLockscreenOrShadeVisible(false)
                testScope.runCurrent()
                executor.runAllReady()
            }

            // THEN status bar service is notified
            verify(iStatusBarService).onPanelHidden()
@@ -198,7 +462,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {

    @Test
    fun lockscreenShadeInteractive_presenterCollapsed_notifEffectsNotCleared() =
        testScope.runTest {
        kosmos.runTest {
            underTest.start()
            keyguardRepository.setStatusBarState(StatusBarState.SHADE)

@@ -213,7 +477,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {

    @Test
    fun lockscreenShadeInteractive_nullPresenter_notifEffectsNotCleared() =
        testScope.runTest {
        kosmos.runTest {
            underTest.start()
            keyguardRepository.setStatusBarState(StatusBarState.SHADE)

@@ -228,7 +492,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {

    @Test
    fun lockscreenShadeInteractive_stateKeyguard_notifEffectsNotCleared() =
        testScope.runTest {
        kosmos.runTest {
            underTest.start()
            whenever(notificationPresenter.isPresenterFullyCollapsed).thenReturn(false)

@@ -243,7 +507,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {

    @Test
    fun lockscreenShadeInteractive_stateShade_presenterNotCollapsed_notifEffectsCleared() =
        testScope.runTest {
        kosmos.runTest {
            underTest.start()
            whenever(notificationPresenter.isPresenterFullyCollapsed).thenReturn(false)

@@ -258,7 +522,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {

    @Test
    fun lockscreenShadeInteractive_stateShadeLocked_presenterNotCollapsed_notifEffectsCleared() =
        testScope.runTest {
        kosmos.runTest {
            underTest.start()
            whenever(notificationPresenter.isPresenterFullyCollapsed).thenReturn(false)

@@ -274,7 +538,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {
    @Test
    @DisableFlags(NotificationsLiveDataStoreRefactor.FLAG_NAME)
    fun lockscreenShadeInteractive_hasHeadsUpAndNotifPresenterCollapsed_flagOff_notifCountOne() =
        testScope.runTest {
        kosmos.runTest {
            underTest.start()

            whenever(headsUpManager.hasPinnedHeadsUp()).thenReturn(true)
@@ -291,7 +555,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {
    @Test
    @EnableFlags(NotificationsLiveDataStoreRefactor.FLAG_NAME)
    fun lockscreenShadeInteractive_hasHeadsUpAndNotifPresenterCollapsed_flagOn_notifCountOne() =
        testScope.runTest {
        kosmos.runTest {
            underTest.start()

            whenever(headsUpManager.hasPinnedHeadsUp()).thenReturn(true)
@@ -307,7 +571,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {

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

            whenever(headsUpManager.hasPinnedHeadsUp()).thenReturn(true)
@@ -323,7 +587,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {
    @Test
    @DisableFlags(NotificationsLiveDataStoreRefactor.FLAG_NAME)
    fun lockscreenShadeInteractive_noHeadsUp_flagOff_notifCountMatchesNotifController() =
        testScope.runTest {
        kosmos.runTest {
            underTest.start()
            whenever(notificationPresenter.isPresenterFullyCollapsed).thenReturn(true)

@@ -340,7 +604,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {
    @Test
    @EnableFlags(NotificationsLiveDataStoreRefactor.FLAG_NAME)
    fun lockscreenShadeInteractive_noHeadsUp_flagOn_notifCountMatchesNotifController() =
        testScope.runTest {
        kosmos.runTest {
            underTest.start()
            whenever(notificationPresenter.isPresenterFullyCollapsed).thenReturn(true)

@@ -357,7 +621,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {
    @Test
    @DisableFlags(NotificationsLiveDataStoreRefactor.FLAG_NAME)
    fun lockscreenShadeInteractive_notifPresenterNotCollapsed_flagOff_notifCountMatchesNotifController() =
        testScope.runTest {
        kosmos.runTest {
            underTest.start()
            whenever(headsUpManager.hasPinnedHeadsUp()).thenReturn(true)

@@ -374,7 +638,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {
    @Test
    @EnableFlags(NotificationsLiveDataStoreRefactor.FLAG_NAME)
    fun lockscreenShadeInteractive_notifPresenterNotCollapsed_flagOn_notifCountMatchesNotifController() =
        testScope.runTest {
        kosmos.runTest {
            underTest.start()
            whenever(headsUpManager.hasPinnedHeadsUp()).thenReturn(true)

@@ -390,7 +654,7 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {

    @Test
    fun lockscreenShadeInteractive_noHeadsUp_noNotifController_notifCountZero() =
        testScope.runTest {
        kosmos.runTest {
            underTest.start()
            whenever(notificationPresenter.isPresenterFullyCollapsed).thenReturn(true)

@@ -405,7 +669,14 @@ class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {
        }

    private fun makeLockscreenShadeVisible() {
        if (SceneContainerFlag.isEnabled) {
            kosmos.sceneInteractor.setTransitionState(
                flowOf(ObservableTransitionState.Idle(Scenes.Lockscreen))
            )
        } else {
            underTest.setIsLockscreenOrShadeVisible(true)
        }

        powerInteractor.setAwakeForTest()
        testScope.runCurrent()
        executor.runAllReady()