diff options
9 files changed, 113 insertions, 26 deletions
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt index d669006c68d3..ddeb05b39e53 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt @@ -23,6 +23,7 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.scene.SceneTestUtils +import com.android.systemui.scene.sceneKeys import com.android.systemui.scene.shared.model.ObservableTransitionState import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.scene.shared.model.SceneModel @@ -70,10 +71,8 @@ class SceneContainerRepositoryTest : SysuiTestCase() { @Test(expected = IllegalStateException::class) fun setDesiredScene_noSuchSceneInContainer_throws() { - val underTest = - utils.fakeSceneContainerRepository( - utils.fakeSceneContainerConfig(listOf(SceneKey.QuickSettings, SceneKey.Lockscreen)), - ) + utils.kosmos.sceneKeys = listOf(SceneKey.QuickSettings, SceneKey.Lockscreen) + val underTest = utils.fakeSceneContainerRepository(utils.fakeSceneContainerConfig()) underTest.setDesiredScene(SceneModel(SceneKey.Shade)) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt index c0b586195eca..f6362fe528ed 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt @@ -27,6 +27,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.domain.model.AuthenticationMethodModel import com.android.systemui.classifier.FalsingCollector import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.kosmos.testScope import com.android.systemui.model.SysUiState import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java index 8e0cf7d7f695..55a44ae34ac6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java @@ -172,7 +172,7 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { mTestScope.getBackgroundScope(), new SceneContainerRepository( mTestScope.getBackgroundScope(), - mUtils.fakeSceneContainerConfig(mUtils.fakeSceneKeys())), + mUtils.fakeSceneContainerConfig()), powerRepository, mock(SceneLogger.class)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java index 2f45b1260dc2..d4b35a9b1515 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java @@ -207,7 +207,7 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase { mTestScope.getBackgroundScope(), new SceneContainerRepository( mTestScope.getBackgroundScope(), - mUtils.fakeSceneContainerConfig(mUtils.fakeSceneKeys())), + mUtils.fakeSceneContainerConfig()), powerRepository, mock(SceneLogger.class)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java index 8309b85620bd..2e191b140e10 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java @@ -395,7 +395,7 @@ public class BubblesTest extends SysuiTestCase { mTestScope.getBackgroundScope(), new SceneContainerRepository( mTestScope.getBackgroundScope(), - mUtils.fakeSceneContainerConfig(mUtils.fakeSceneKeys())), + mUtils.fakeSceneContainerConfig()), powerRepository, mock(SceneLogger.class)); diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt new file mode 100644 index 000000000000..cc843b536756 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt @@ -0,0 +1,8 @@ +package com.android.systemui.kosmos + +import com.android.systemui.kosmos.Kosmos.Fixture +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope + +val Kosmos.testDispatcher by Fixture { StandardTestDispatcher() } +val Kosmos.testScope by Fixture { TestScope(testDispatcher) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/Kosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/Kosmos.kt new file mode 100644 index 000000000000..c74cdd4ca4c4 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/Kosmos.kt @@ -0,0 +1,69 @@ +package com.android.systemui.kosmos + +import kotlin.reflect.KProperty + +// (Historical note: The name Kosmos is meant to invoke "Kotlin", the "Object Mother" pattern +// (https://martinfowler.com/bliki/ObjectMother.html), and of course the Greek word "kosmos" for +// the "order of the world" (https://en.wiktionary.org/wiki/%CE%BA%CF%8C%CF%83%CE%BC%CE%BF%CF%82) +/** + * Each Kosmos is its own self-contained set of fixtures, which may reference each other. Fixtures + * can be defined through extension properties in any file: + * ``` + * // fixture that must be set: + * var Kosmos.context by Fixture<Context>() + * + * // fixture with overrideable default. + * var Kosmos.landscapeMode by Fixture { false } + * + * // fixture forbidding override (note `val`, and referencing context fixture from above) + * val Kosmos.lifecycleScope by Fixture { context.lifecycleScope } + * ``` + * + * To use the fixtures, create an instance of Kosmos and retrieve the values you need: + * ``` + * val k = Kosmos() + * k.context = mContext + * val underTest = YourInteractor( + * context = k.context, + * landscapeMode = k.landscapeMode, + * ) + * ``` + */ +class Kosmos { + private val map: MutableMap<String, Any?> = mutableMapOf() + private val gotten: MutableSet<String> = mutableSetOf() + + /** + * A value in the kosmos that has a single value once it's read. It can be overridden before + * first use only; all objects that are dependent on this fixture will get the same value. + * + * Example classic uses would be a clock, filesystem, or singleton controller. + * + * If no [creator] parameter is provided, the fixture must be set before use. + */ + class Fixture<T>(private val creator: (Kosmos.() -> T)? = null) { + operator fun getValue(thisRef: Kosmos, property: KProperty<*>): T { + thisRef.gotten.add(property.name) + @Suppress("UNCHECKED_CAST") + if (!thisRef.map.contains(property.name)) { + if (creator == null) { + throw IllegalStateException( + "Fixture ${property.name} has no default, and is read before set." + ) + } else { + val nonNullCreator = creator + // The Kotlin compiler seems to need this odd workaround + thisRef.map[property.name] = thisRef.nonNullCreator() + } + } + return thisRef.map[property.name] as T + } + + operator fun setValue(thisRef: Kosmos, property: KProperty<*>, value: T) { + check(!thisRef.gotten.contains(property.name)) { + "Tried to set fixture '${property.name}' after it's already been read." + } + thisRef.map[property.name] = value + } + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt new file mode 100644 index 000000000000..8fc419cadb21 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt @@ -0,0 +1,20 @@ +package com.android.systemui.scene + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture +import com.android.systemui.scene.shared.model.SceneContainerConfig +import com.android.systemui.scene.shared.model.SceneKey + +var Kosmos.sceneKeys by Fixture { + listOf( + SceneKey.QuickSettings, + SceneKey.Shade, + SceneKey.Lockscreen, + SceneKey.Bouncer, + SceneKey.Gone, + SceneKey.Communal, + ) +} + +val Kosmos.initialSceneKey by Fixture { SceneKey.Lockscreen } +val Kosmos.sceneContainerConfig by Fixture { SceneContainerConfig(sceneKeys, initialSceneKey) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt index 7c113e823bbc..217067b307bc 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt @@ -51,6 +51,9 @@ import com.android.systemui.keyguard.data.repository.FakeTrustRepository import com.android.systemui.keyguard.data.repository.KeyguardRepository import com.android.systemui.keyguard.data.repository.TrustRepository import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testDispatcher +import com.android.systemui.kosmos.testScope import com.android.systemui.power.data.repository.FakePowerRepository import com.android.systemui.power.domain.interactor.PowerInteractorFactory import com.android.systemui.scene.data.repository.SceneContainerRepository @@ -71,8 +74,6 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.test.StandardTestDispatcher -import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.currentTime /** @@ -83,8 +84,9 @@ import kotlinx.coroutines.test.currentTime class SceneTestUtils( test: SysuiTestCase, ) { - val testDispatcher = StandardTestDispatcher() - val testScope = TestScope(testDispatcher) + val kosmos = Kosmos() + val testDispatcher = kosmos.testDispatcher + val testScope = kosmos.testScope val featureFlags = FakeFeatureFlagsClassic().apply { set(Flags.FACE_AUTH_REFACTOR, false) @@ -129,23 +131,11 @@ class SceneTestUtils( } fun fakeSceneKeys(): List<SceneKey> { - return listOf( - SceneKey.QuickSettings, - SceneKey.Shade, - SceneKey.Lockscreen, - SceneKey.Bouncer, - SceneKey.Gone, - SceneKey.Communal, - ) + return kosmos.sceneKeys } - fun fakeSceneContainerConfig( - sceneKeys: List<SceneKey> = fakeSceneKeys(), - ): SceneContainerConfig { - return SceneContainerConfig( - sceneKeys = sceneKeys, - initialSceneKey = SceneKey.Lockscreen, - ) + fun fakeSceneContainerConfig(): SceneContainerConfig { + return kosmos.sceneContainerConfig } @JvmOverloads |