summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt262
1 files changed, 65 insertions, 197 deletions
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
index 0b14be1eefbd..925b2e574962 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
@@ -42,14 +42,11 @@ import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import java.util.UUID
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
-import kotlinx.coroutines.yield
-import org.junit.After
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
@@ -68,7 +65,7 @@ class MobileIconsInteractorTest : SysuiTestCase() {
set(Flags.FILTER_PROVISIONING_NETWORK_SUBSCRIPTIONS, true)
}
- private val testDispatcher = UnconfinedTestDispatcher()
+ private val testDispatcher = StandardTestDispatcher()
private val testScope = TestScope(testDispatcher)
private val tableLogBuffer =
@@ -113,17 +110,12 @@ class MobileIconsInteractorTest : SysuiTestCase() {
)
}
- @After fun tearDown() {}
-
@Test
fun filteredSubscriptions_default() =
testScope.runTest {
- var latest: List<SubscriptionModel>? = null
- val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.filteredSubscriptions)
assertThat(latest).isEqualTo(listOf<SubscriptionModel>())
-
- job.cancel()
}
// Based on the logic from the old pipeline, we'll never filter subs when there are more than 2
@@ -133,12 +125,9 @@ class MobileIconsInteractorTest : SysuiTestCase() {
connectionsRepository.setSubscriptions(listOf(SUB_1, SUB_3_OPP, SUB_4_OPP))
connectionsRepository.setActiveMobileDataSubscriptionId(SUB_4_ID)
- var latest: List<SubscriptionModel>? = null
- val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.filteredSubscriptions)
assertThat(latest).isEqualTo(listOf(SUB_1, SUB_3_OPP, SUB_4_OPP))
-
- job.cancel()
}
@Test
@@ -146,12 +135,9 @@ class MobileIconsInteractorTest : SysuiTestCase() {
testScope.runTest {
connectionsRepository.setSubscriptions(listOf(SUB_1, SUB_2))
- var latest: List<SubscriptionModel>? = null
- val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.filteredSubscriptions)
assertThat(latest).isEqualTo(listOf(SUB_1, SUB_2))
-
- job.cancel()
}
@Test
@@ -160,12 +146,9 @@ class MobileIconsInteractorTest : SysuiTestCase() {
connectionsRepository.setSubscriptions(listOf(SUB_3_OPP, SUB_4_OPP))
connectionsRepository.setActiveMobileDataSubscriptionId(SUB_3_ID)
- var latest: List<SubscriptionModel>? = null
- val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.filteredSubscriptions)
assertThat(latest).isEqualTo(listOf(SUB_3_OPP, SUB_4_OPP))
-
- job.cancel()
}
@Test
@@ -180,12 +163,9 @@ class MobileIconsInteractorTest : SysuiTestCase() {
connectionsRepository.setSubscriptions(listOf(sub1, sub2))
connectionsRepository.setActiveMobileDataSubscriptionId(SUB_1_ID)
- var latest: List<SubscriptionModel>? = null
- val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.filteredSubscriptions)
assertThat(latest).isEqualTo(listOf(sub1, sub2))
-
- job.cancel()
}
@Test
@@ -202,13 +182,10 @@ class MobileIconsInteractorTest : SysuiTestCase() {
whenever(carrierConfigTracker.alwaysShowPrimarySignalBarInOpportunisticNetworkDefault)
.thenReturn(false)
- var latest: List<SubscriptionModel>? = null
- val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.filteredSubscriptions)
// Filtered subscriptions should show the active one when the config is false
assertThat(latest).isEqualTo(listOf(sub3))
-
- job.cancel()
}
@Test
@@ -225,13 +202,10 @@ class MobileIconsInteractorTest : SysuiTestCase() {
whenever(carrierConfigTracker.alwaysShowPrimarySignalBarInOpportunisticNetworkDefault)
.thenReturn(false)
- var latest: List<SubscriptionModel>? = null
- val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.filteredSubscriptions)
// Filtered subscriptions should show the active one when the config is false
assertThat(latest).isEqualTo(listOf(sub4))
-
- job.cancel()
}
@Test
@@ -248,14 +222,11 @@ class MobileIconsInteractorTest : SysuiTestCase() {
whenever(carrierConfigTracker.alwaysShowPrimarySignalBarInOpportunisticNetworkDefault)
.thenReturn(true)
- var latest: List<SubscriptionModel>? = null
- val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.filteredSubscriptions)
// Filtered subscriptions should show the primary (non-opportunistic) if the config is
// true
assertThat(latest).isEqualTo(listOf(sub1))
-
- job.cancel()
}
@Test
@@ -272,14 +243,11 @@ class MobileIconsInteractorTest : SysuiTestCase() {
whenever(carrierConfigTracker.alwaysShowPrimarySignalBarInOpportunisticNetworkDefault)
.thenReturn(true)
- var latest: List<SubscriptionModel>? = null
- val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.filteredSubscriptions)
// Filtered subscriptions should show the primary (non-opportunistic) if the config is
// true
assertThat(latest).isEqualTo(listOf(sub1))
-
- job.cancel()
}
@Test
@@ -297,12 +265,9 @@ class MobileIconsInteractorTest : SysuiTestCase() {
whenever(carrierConfigTracker.alwaysShowPrimarySignalBarInOpportunisticNetworkDefault)
.thenReturn(false)
- var latest: List<SubscriptionModel>? = null
- val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.filteredSubscriptions)
assertThat(latest).isEqualTo(listOf(sub3))
-
- job.cancel()
}
@Test
@@ -320,12 +285,9 @@ class MobileIconsInteractorTest : SysuiTestCase() {
whenever(carrierConfigTracker.alwaysShowPrimarySignalBarInOpportunisticNetworkDefault)
.thenReturn(false)
- var latest: List<SubscriptionModel>? = null
- val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.filteredSubscriptions)
assertThat(latest).isEqualTo(listOf(sub1))
-
- job.cancel()
}
@Test
@@ -449,310 +411,241 @@ class MobileIconsInteractorTest : SysuiTestCase() {
fun activeDataConnection_turnedOn() =
testScope.runTest {
CONNECTION_1.setDataEnabled(true)
- var latest: Boolean? = null
- val job =
- underTest.activeDataConnectionHasDataEnabled.onEach { latest = it }.launchIn(this)
- assertThat(latest).isTrue()
+ val latest by collectLastValue(underTest.activeDataConnectionHasDataEnabled)
- job.cancel()
+ assertThat(latest).isTrue()
}
@Test
fun activeDataConnection_turnedOff() =
testScope.runTest {
CONNECTION_1.setDataEnabled(true)
- var latest: Boolean? = null
- val job =
- underTest.activeDataConnectionHasDataEnabled.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.activeDataConnectionHasDataEnabled)
CONNECTION_1.setDataEnabled(false)
- yield()
assertThat(latest).isFalse()
-
- job.cancel()
}
@Test
fun activeDataConnection_invalidSubId() =
testScope.runTest {
- var latest: Boolean? = null
- val job =
- underTest.activeDataConnectionHasDataEnabled.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.activeDataConnectionHasDataEnabled)
connectionsRepository.setActiveMobileDataSubscriptionId(INVALID_SUBSCRIPTION_ID)
- yield()
// An invalid active subId should tell us that data is off
assertThat(latest).isFalse()
-
- job.cancel()
}
@Test
fun failedConnection_default_validated_notFailed() =
testScope.runTest {
- var latest: Boolean? = null
- val job = underTest.isDefaultConnectionFailed.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.isDefaultConnectionFailed)
connectionsRepository.mobileIsDefault.value = true
connectionsRepository.defaultConnectionIsValidated.value = true
- yield()
assertThat(latest).isFalse()
-
- job.cancel()
}
@Test
fun failedConnection_notDefault_notValidated_notFailed() =
testScope.runTest {
- var latest: Boolean? = null
- val job = underTest.isDefaultConnectionFailed.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.isDefaultConnectionFailed)
connectionsRepository.mobileIsDefault.value = false
connectionsRepository.defaultConnectionIsValidated.value = false
- yield()
assertThat(latest).isFalse()
-
- job.cancel()
}
@Test
fun failedConnection_default_notValidated_failed() =
testScope.runTest {
- var latest: Boolean? = null
- val job = underTest.isDefaultConnectionFailed.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.isDefaultConnectionFailed)
connectionsRepository.mobileIsDefault.value = true
connectionsRepository.defaultConnectionIsValidated.value = false
- yield()
assertThat(latest).isTrue()
-
- job.cancel()
}
@Test
fun failedConnection_carrierMergedDefault_notValidated_failed() =
testScope.runTest {
- var latest: Boolean? = null
- val job = underTest.isDefaultConnectionFailed.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.isDefaultConnectionFailed)
connectionsRepository.hasCarrierMergedConnection.value = true
connectionsRepository.defaultConnectionIsValidated.value = false
- yield()
assertThat(latest).isTrue()
-
- job.cancel()
}
/** Regression test for b/275076959. */
@Test
fun failedConnection_dataSwitchInSameGroup_notFailed() =
testScope.runTest {
- var latest: Boolean? = null
- val job = underTest.isDefaultConnectionFailed.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.isDefaultConnectionFailed)
connectionsRepository.mobileIsDefault.value = true
connectionsRepository.defaultConnectionIsValidated.value = true
+ runCurrent()
// WHEN there's a data change in the same subscription group
connectionsRepository.activeSubChangedInGroupEvent.emit(Unit)
connectionsRepository.defaultConnectionIsValidated.value = false
+ runCurrent()
// THEN the default connection is *not* marked as failed because of forced validation
assertThat(latest).isFalse()
-
- job.cancel()
}
@Test
fun failedConnection_dataSwitchNotInSameGroup_isFailed() =
testScope.runTest {
- var latestConnectionFailed: Boolean? = null
- val job =
- underTest.isDefaultConnectionFailed
- .onEach { latestConnectionFailed = it }
- .launchIn(this)
+ val latest by collectLastValue(underTest.isDefaultConnectionFailed)
+
connectionsRepository.mobileIsDefault.value = true
connectionsRepository.defaultConnectionIsValidated.value = true
+ runCurrent()
// WHEN the connection is invalidated without a activeSubChangedInGroupEvent
connectionsRepository.defaultConnectionIsValidated.value = false
// THEN the connection is immediately marked as failed
- assertThat(latestConnectionFailed).isTrue()
-
- job.cancel()
+ assertThat(latest).isTrue()
}
@Test
fun alwaysShowDataRatIcon_configHasTrue() =
testScope.runTest {
- var latest: Boolean? = null
- val job = underTest.alwaysShowDataRatIcon.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.alwaysShowDataRatIcon)
val config = MobileMappings.Config()
config.alwaysShowDataRatIcon = true
connectionsRepository.defaultDataSubRatConfig.value = config
- yield()
assertThat(latest).isTrue()
-
- job.cancel()
}
@Test
fun alwaysShowDataRatIcon_configHasFalse() =
testScope.runTest {
- var latest: Boolean? = null
- val job = underTest.alwaysShowDataRatIcon.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.alwaysShowDataRatIcon)
val config = MobileMappings.Config()
config.alwaysShowDataRatIcon = false
connectionsRepository.defaultDataSubRatConfig.value = config
- yield()
assertThat(latest).isFalse()
-
- job.cancel()
}
@Test
fun alwaysUseCdmaLevel_configHasTrue() =
testScope.runTest {
- var latest: Boolean? = null
- val job = underTest.alwaysUseCdmaLevel.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.alwaysUseCdmaLevel)
val config = MobileMappings.Config()
config.alwaysShowCdmaRssi = true
connectionsRepository.defaultDataSubRatConfig.value = config
- yield()
assertThat(latest).isTrue()
-
- job.cancel()
}
@Test
fun alwaysUseCdmaLevel_configHasFalse() =
testScope.runTest {
- var latest: Boolean? = null
- val job = underTest.alwaysUseCdmaLevel.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.alwaysUseCdmaLevel)
val config = MobileMappings.Config()
config.alwaysShowCdmaRssi = false
connectionsRepository.defaultDataSubRatConfig.value = config
- yield()
assertThat(latest).isFalse()
-
- job.cancel()
}
@Test
fun isSingleCarrier_zeroSubscriptions_false() =
testScope.runTest {
- var latest: Boolean? = true
- val job = underTest.isSingleCarrier.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.isSingleCarrier)
connectionsRepository.setSubscriptions(emptyList())
- assertThat(latest).isFalse()
- job.cancel()
+ assertThat(latest).isFalse()
}
@Test
fun isSingleCarrier_oneSubscription_true() =
testScope.runTest {
- var latest: Boolean? = false
- val job = underTest.isSingleCarrier.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.isSingleCarrier)
connectionsRepository.setSubscriptions(listOf(SUB_1))
- assertThat(latest).isTrue()
- job.cancel()
+ assertThat(latest).isTrue()
}
@Test
fun isSingleCarrier_twoSubscriptions_false() =
testScope.runTest {
- var latest: Boolean? = true
- val job = underTest.isSingleCarrier.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.isSingleCarrier)
connectionsRepository.setSubscriptions(listOf(SUB_1, SUB_2))
- assertThat(latest).isFalse()
- job.cancel()
+ assertThat(latest).isFalse()
}
@Test
fun isSingleCarrier_updates() =
testScope.runTest {
- var latest: Boolean? = false
- val job = underTest.isSingleCarrier.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.isSingleCarrier)
connectionsRepository.setSubscriptions(listOf(SUB_1))
assertThat(latest).isTrue()
connectionsRepository.setSubscriptions(listOf(SUB_1, SUB_2))
assertThat(latest).isFalse()
-
- job.cancel()
}
@Test
fun mobileIsDefault_mobileFalseAndCarrierMergedFalse_false() =
testScope.runTest {
- var latest: Boolean? = null
- val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.mobileIsDefault)
connectionsRepository.mobileIsDefault.value = false
connectionsRepository.hasCarrierMergedConnection.value = false
assertThat(latest).isFalse()
-
- job.cancel()
}
@Test
fun mobileIsDefault_mobileTrueAndCarrierMergedFalse_true() =
testScope.runTest {
- var latest: Boolean? = null
- val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.mobileIsDefault)
connectionsRepository.mobileIsDefault.value = true
connectionsRepository.hasCarrierMergedConnection.value = false
assertThat(latest).isTrue()
-
- job.cancel()
}
/** Regression test for b/272586234. */
@Test
fun mobileIsDefault_mobileFalseAndCarrierMergedTrue_true() =
testScope.runTest {
- var latest: Boolean? = null
- val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.mobileIsDefault)
connectionsRepository.mobileIsDefault.value = false
connectionsRepository.hasCarrierMergedConnection.value = true
assertThat(latest).isTrue()
-
- job.cancel()
}
@Test
fun mobileIsDefault_updatesWhenRepoUpdates() =
testScope.runTest {
- var latest: Boolean? = null
- val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.mobileIsDefault)
connectionsRepository.mobileIsDefault.value = true
assertThat(latest).isTrue()
@@ -762,8 +655,6 @@ class MobileIconsInteractorTest : SysuiTestCase() {
connectionsRepository.hasCarrierMergedConnection.value = true
assertThat(latest).isTrue()
-
- job.cancel()
}
// The data switch tests are mostly testing the [forcingCellularValidation] flow, but that flow
@@ -772,95 +663,79 @@ class MobileIconsInteractorTest : SysuiTestCase() {
@Test
fun dataSwitch_inSameGroup_validatedMatchesPreviousValue_expiresAfter2s() =
testScope.runTest {
- var latestConnectionFailed: Boolean? = null
- val job =
- underTest.isDefaultConnectionFailed
- .onEach { latestConnectionFailed = it }
- .launchIn(this)
+ val latest by collectLastValue(underTest.isDefaultConnectionFailed)
connectionsRepository.mobileIsDefault.value = true
connectionsRepository.defaultConnectionIsValidated.value = true
+ runCurrent()
// Trigger a data change in the same subscription group that's not yet validated
connectionsRepository.activeSubChangedInGroupEvent.emit(Unit)
connectionsRepository.defaultConnectionIsValidated.value = false
+ runCurrent()
// After 1s, the force validation bit is still present, so the connection is not marked
// as failed
advanceTimeBy(1000)
- assertThat(latestConnectionFailed).isFalse()
+ assertThat(latest).isFalse()
// After 2s, the force validation expires so the connection updates to failed
advanceTimeBy(1001)
- assertThat(latestConnectionFailed).isTrue()
-
- job.cancel()
+ assertThat(latest).isTrue()
}
@Test
fun dataSwitch_inSameGroup_notValidated_immediatelyMarkedAsFailed() =
testScope.runTest {
- var latestConnectionFailed: Boolean? = null
- val job =
- underTest.isDefaultConnectionFailed
- .onEach { latestConnectionFailed = it }
- .launchIn(this)
+ val latest by collectLastValue(underTest.isDefaultConnectionFailed)
connectionsRepository.mobileIsDefault.value = true
connectionsRepository.defaultConnectionIsValidated.value = false
+ runCurrent()
connectionsRepository.activeSubChangedInGroupEvent.emit(Unit)
- assertThat(latestConnectionFailed).isTrue()
-
- job.cancel()
+ assertThat(latest).isTrue()
}
@Test
fun dataSwitch_loseValidation_thenSwitchHappens_clearsForcedBit() =
testScope.runTest {
- var latestConnectionFailed: Boolean? = null
- val job =
- underTest.isDefaultConnectionFailed
- .onEach { latestConnectionFailed = it }
- .launchIn(this)
+ val latest by collectLastValue(underTest.isDefaultConnectionFailed)
// GIVEN the network starts validated
connectionsRepository.mobileIsDefault.value = true
connectionsRepository.defaultConnectionIsValidated.value = true
+ runCurrent()
// WHEN a data change happens in the same group
connectionsRepository.activeSubChangedInGroupEvent.emit(Unit)
// WHEN the validation bit is lost
connectionsRepository.defaultConnectionIsValidated.value = false
+ runCurrent()
// WHEN another data change happens in the same group
connectionsRepository.activeSubChangedInGroupEvent.emit(Unit)
// THEN the forced validation bit is still used...
- assertThat(latestConnectionFailed).isFalse()
+ assertThat(latest).isFalse()
advanceTimeBy(1000)
- assertThat(latestConnectionFailed).isFalse()
+ assertThat(latest).isFalse()
// ... but expires after 2s
advanceTimeBy(1001)
- assertThat(latestConnectionFailed).isTrue()
-
- job.cancel()
+ assertThat(latest).isTrue()
}
@Test
fun dataSwitch_whileAlreadyForcingValidation_resetsClock() =
testScope.runTest {
- var latestConnectionFailed: Boolean? = null
- val job =
- underTest.isDefaultConnectionFailed
- .onEach { latestConnectionFailed = it }
- .launchIn(this)
+ val latest by collectLastValue(underTest.isDefaultConnectionFailed)
connectionsRepository.mobileIsDefault.value = true
connectionsRepository.defaultConnectionIsValidated.value = true
+ runCurrent()
connectionsRepository.activeSubChangedInGroupEvent.emit(Unit)
@@ -869,44 +744,37 @@ class MobileIconsInteractorTest : SysuiTestCase() {
// WHEN another change in same group event happens
connectionsRepository.activeSubChangedInGroupEvent.emit(Unit)
connectionsRepository.defaultConnectionIsValidated.value = false
+ runCurrent()
// THEN the forced validation remains for exactly 2 more seconds from now
// 1.500s from second event
advanceTimeBy(1500)
- assertThat(latestConnectionFailed).isFalse()
+ assertThat(latest).isFalse()
// 2.001s from the second event
advanceTimeBy(501)
- assertThat(latestConnectionFailed).isTrue()
-
- job.cancel()
+ assertThat(latest).isTrue()
}
@Test
fun isForceHidden_repoHasMobileHidden_true() =
testScope.runTest {
- var latest: Boolean? = null
- val job = underTest.isForceHidden.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.isForceHidden)
connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.MOBILE))
assertThat(latest).isTrue()
-
- job.cancel()
}
@Test
fun isForceHidden_repoDoesNotHaveMobileHidden_false() =
testScope.runTest {
- var latest: Boolean? = null
- val job = underTest.isForceHidden.onEach { latest = it }.launchIn(this)
+ val latest by collectLastValue(underTest.isForceHidden)
connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.WIFI))
assertThat(latest).isFalse()
-
- job.cancel()
}
@Test