Loading packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt +42 −2 Original line number Diff line number Diff line Loading @@ -58,13 +58,16 @@ import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupReposi import com.android.systemui.util.CarrierConfigTracker import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Assume.assumeFalse import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @TestableLooper.RunWithLooper @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) class InternetTileDataInteractorTest : SysuiTestCase() { Loading Loading @@ -141,6 +144,7 @@ class InternetTileDataInteractorTest : SysuiTestCase() { underTest = InternetTileDataInteractor( context, testScope.coroutineContext, testScope.backgroundScope, airplaneModeRepository, connectivityRepository, Loading Loading @@ -433,8 +437,44 @@ class InternetTileDataInteractorTest : SysuiTestCase() { .isEqualTo(expectedCd) } /** * We expect a RuntimeException because [underTest] instantiates a SignalDrawable on the * provided context, and so the SignalDrawable constructor attempts to instantiate a Handler() * on the mentioned context. Since that context does not have a looper assigned to it, the * handler instantiation will throw a RuntimeException. * * TODO(b/338068066): Robolectric behavior differs in that it does not throw the exception * So either we should make Robolectric behvase similar to the device test, or change this * test to look for a different signal than the exception, when run by Robolectric. For now * we just assume the test is not Robolectric. */ @Test(expected = java.lang.RuntimeException::class) fun mobileDefault_usesNetworkNameAndIcon_throwsRunTimeException() = testScope.runTest { assumeFalse(isRobolectricTest()); collectLastValue(underTest.tileData(testUser, flowOf(DataUpdateTrigger.InitialRequest))) connectivityRepository.setMobileConnected() mobileConnectionsRepository.mobileIsDefault.value = true mobileConnectionRepository.apply { setAllLevels(3) setAllRoaming(false) networkName.value = NetworkNameModel.Default("test network") } runCurrent() } /** * See [mobileDefault_usesNetworkNameAndIcon_throwsRunTimeException] for description of the * problem this test solves. The solution here is to assign a looper to the context via * RunWithLooper. In the production code, the solution is to use a Main CoroutineContext for * creating the SignalDrawable. */ @TestableLooper.RunWithLooper @Test fun mobileDefault_usesNetworkNameAndIcon() = fun mobileDefault_run_withLooper_usesNetworkNameAndIcon() = testScope.runTest { val latest by collectLastValue( Loading packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractor.kt +43 −32 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import com.android.systemui.common.shared.model.ContentDescription.Companion.loa import com.android.systemui.common.shared.model.Icon import com.android.systemui.common.shared.model.Text import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor import com.android.systemui.qs.tiles.impl.internet.domain.model.InternetTileModel Loading @@ -38,7 +39,9 @@ import com.android.systemui.statusbar.pipeline.shared.data.repository.Connectivi import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon import com.android.systemui.utils.coroutines.flow.mapLatestConflated import javax.inject.Inject import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow Loading @@ -48,6 +51,7 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.withContext @OptIn(ExperimentalCoroutinesApi::class) /** Observes internet state changes providing the [InternetTileModel]. */ Loading @@ -55,6 +59,7 @@ class InternetTileDataInteractor @Inject constructor( private val context: Context, @Main private val mainCoroutineContext: CoroutineContext, @Application private val scope: CoroutineScope, airplaneModeRepository: AirplaneModeRepository, private val connectivityRepository: ConnectivityRepository, Loading Loading @@ -115,6 +120,9 @@ constructor( it.signalLevelIcon, mobileDataContentName, ) { networkNameModel, signalIcon, dataContentDescription -> Triple(networkNameModel, signalIcon, dataContentDescription) } .mapLatestConflated { (networkNameModel, signalIcon, dataContentDescription) -> when (signalIcon) { is SignalIconModel.Cellular -> { val secondary = Loading @@ -123,21 +131,24 @@ constructor( dataContentDescription ) val stateLevel = signalIcon.level val drawable = SignalDrawable(context) drawable.setLevel(stateLevel) val drawable = withContext(mainCoroutineContext) { SignalDrawable(context) } drawable.setLevel(signalIcon.level) val loadedIcon = Icon.Loaded(drawable, null) InternetTileModel.Active( secondaryTitle = secondary, icon = loadedIcon, stateDescription = ContentDescription.Loaded(secondary.toString()), stateDescription = ContentDescription.Loaded(secondary.toString()), contentDescription = ContentDescription.Loaded(internetLabel), ) } is SignalIconModel.Satellite -> { val secondary = signalIcon.icon.contentDescription.loadContentDescription(context) signalIcon.icon.contentDescription.loadContentDescription( context ) InternetTileModel.Active( secondaryTitle = secondary, iconId = signalIcon.icon.res, Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt +42 −2 Original line number Diff line number Diff line Loading @@ -58,13 +58,16 @@ import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupReposi import com.android.systemui.util.CarrierConfigTracker import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Assume.assumeFalse import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @TestableLooper.RunWithLooper @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) class InternetTileDataInteractorTest : SysuiTestCase() { Loading Loading @@ -141,6 +144,7 @@ class InternetTileDataInteractorTest : SysuiTestCase() { underTest = InternetTileDataInteractor( context, testScope.coroutineContext, testScope.backgroundScope, airplaneModeRepository, connectivityRepository, Loading Loading @@ -433,8 +437,44 @@ class InternetTileDataInteractorTest : SysuiTestCase() { .isEqualTo(expectedCd) } /** * We expect a RuntimeException because [underTest] instantiates a SignalDrawable on the * provided context, and so the SignalDrawable constructor attempts to instantiate a Handler() * on the mentioned context. Since that context does not have a looper assigned to it, the * handler instantiation will throw a RuntimeException. * * TODO(b/338068066): Robolectric behavior differs in that it does not throw the exception * So either we should make Robolectric behvase similar to the device test, or change this * test to look for a different signal than the exception, when run by Robolectric. For now * we just assume the test is not Robolectric. */ @Test(expected = java.lang.RuntimeException::class) fun mobileDefault_usesNetworkNameAndIcon_throwsRunTimeException() = testScope.runTest { assumeFalse(isRobolectricTest()); collectLastValue(underTest.tileData(testUser, flowOf(DataUpdateTrigger.InitialRequest))) connectivityRepository.setMobileConnected() mobileConnectionsRepository.mobileIsDefault.value = true mobileConnectionRepository.apply { setAllLevels(3) setAllRoaming(false) networkName.value = NetworkNameModel.Default("test network") } runCurrent() } /** * See [mobileDefault_usesNetworkNameAndIcon_throwsRunTimeException] for description of the * problem this test solves. The solution here is to assign a looper to the context via * RunWithLooper. In the production code, the solution is to use a Main CoroutineContext for * creating the SignalDrawable. */ @TestableLooper.RunWithLooper @Test fun mobileDefault_usesNetworkNameAndIcon() = fun mobileDefault_run_withLooper_usesNetworkNameAndIcon() = testScope.runTest { val latest by collectLastValue( Loading
packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractor.kt +43 −32 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import com.android.systemui.common.shared.model.ContentDescription.Companion.loa import com.android.systemui.common.shared.model.Icon import com.android.systemui.common.shared.model.Text import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor import com.android.systemui.qs.tiles.impl.internet.domain.model.InternetTileModel Loading @@ -38,7 +39,9 @@ import com.android.systemui.statusbar.pipeline.shared.data.repository.Connectivi import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon import com.android.systemui.utils.coroutines.flow.mapLatestConflated import javax.inject.Inject import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow Loading @@ -48,6 +51,7 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.withContext @OptIn(ExperimentalCoroutinesApi::class) /** Observes internet state changes providing the [InternetTileModel]. */ Loading @@ -55,6 +59,7 @@ class InternetTileDataInteractor @Inject constructor( private val context: Context, @Main private val mainCoroutineContext: CoroutineContext, @Application private val scope: CoroutineScope, airplaneModeRepository: AirplaneModeRepository, private val connectivityRepository: ConnectivityRepository, Loading Loading @@ -115,6 +120,9 @@ constructor( it.signalLevelIcon, mobileDataContentName, ) { networkNameModel, signalIcon, dataContentDescription -> Triple(networkNameModel, signalIcon, dataContentDescription) } .mapLatestConflated { (networkNameModel, signalIcon, dataContentDescription) -> when (signalIcon) { is SignalIconModel.Cellular -> { val secondary = Loading @@ -123,21 +131,24 @@ constructor( dataContentDescription ) val stateLevel = signalIcon.level val drawable = SignalDrawable(context) drawable.setLevel(stateLevel) val drawable = withContext(mainCoroutineContext) { SignalDrawable(context) } drawable.setLevel(signalIcon.level) val loadedIcon = Icon.Loaded(drawable, null) InternetTileModel.Active( secondaryTitle = secondary, icon = loadedIcon, stateDescription = ContentDescription.Loaded(secondary.toString()), stateDescription = ContentDescription.Loaded(secondary.toString()), contentDescription = ContentDescription.Loaded(internetLabel), ) } is SignalIconModel.Satellite -> { val secondary = signalIcon.icon.contentDescription.loadContentDescription(context) signalIcon.icon.contentDescription.loadContentDescription( context ) InternetTileModel.Active( secondaryTitle = secondary, iconId = signalIcon.icon.res, Loading