Loading packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt +2 −2 Original line number Diff line number Diff line Loading @@ -203,7 +203,7 @@ private fun SceneScope.FoldSplittable( modifier: Modifier = Modifier, ) { val message: BouncerViewModel.MessageViewModel by viewModel.message.collectAsState() val dialogMessage: String? by viewModel.throttlingDialogMessage.collectAsState() val dialogMessage: String? by viewModel.dialogMessage.collectAsState() var dialog: Dialog? by remember { mutableStateOf(null) } val actionButton: BouncerActionButtonModel? by viewModel.actionButton.collectAsState() val splitRatio = Loading Loading @@ -320,7 +320,7 @@ private fun SceneScope.FoldSplittable( DialogInterface.BUTTON_NEUTRAL, context.getString(R.string.ok), ) { _, _ -> viewModel.onThrottlingDialogDismissed() viewModel.onDialogDismissed() } setCancelable(false) setCanceledOnTouchOutside(false) Loading packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt +46 −47 Original line number Diff line number Diff line Loading @@ -21,9 +21,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository import com.android.systemui.authentication.shared.model.AuthenticationLockoutModel import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel import com.android.systemui.coroutines.collectLastValue import com.android.systemui.scene.SceneTestUtils import com.google.common.truth.Truth.assertThat Loading Loading @@ -76,12 +76,12 @@ class AuthenticationInteractorTest : SysuiTestCase() { @Test fun authenticate_withCorrectPin_succeeds() = testScope.runTest { val throttling by collectLastValue(underTest.throttling) val lockout by collectLastValue(underTest.lockout) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)) .isEqualTo(AuthenticationResult.SUCCEEDED) assertThat(throttling).isNull() assertThat(lockout).isNull() assertThat(utils.authenticationRepository.lockoutStartedReportCount).isEqualTo(0) } Loading Loading @@ -130,14 +130,14 @@ class AuthenticationInteractorTest : SysuiTestCase() { @Test fun authenticate_withCorrectPassword_succeeds() = testScope.runTest { val throttling by collectLastValue(underTest.throttling) val lockout by collectLastValue(underTest.lockout) utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Password ) assertThat(underTest.authenticate("password".toList())) .isEqualTo(AuthenticationResult.SUCCEEDED) assertThat(throttling).isNull() assertThat(lockout).isNull() assertThat(utils.authenticationRepository.lockoutStartedReportCount).isEqualTo(0) } Loading Loading @@ -187,7 +187,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { fun tryAutoConfirm_withAutoConfirmPinAndShorterPin_returnsNull() = testScope.runTest { val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled) val throttling by collectLastValue(underTest.throttling) val lockout by collectLastValue(underTest.lockout) utils.authenticationRepository.apply { setAuthenticationMethod(AuthenticationMethodModel.Pin) setAutoConfirmFeatureEnabled(true) Loading @@ -203,7 +203,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { ) ) .isEqualTo(AuthenticationResult.SKIPPED) assertThat(throttling).isNull() assertThat(lockout).isNull() assertThat(utils.authenticationRepository.lockoutStartedReportCount).isEqualTo(0) } Loading Loading @@ -265,7 +265,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { } @Test fun tryAutoConfirm_withAutoConfirmCorrectPinButDuringThrottling_returnsNull() = fun tryAutoConfirm_withAutoConfirmCorrectPinButDuringLockout_returnsNull() = testScope.runTest { val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled) val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked) Loading @@ -273,7 +273,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { utils.authenticationRepository.apply { setAuthenticationMethod(AuthenticationMethodModel.Pin) setAutoConfirmFeatureEnabled(true) setThrottleDuration(42) setLockoutDuration(42) } val authResult = Loading Loading @@ -334,30 +334,30 @@ class AuthenticationInteractorTest : SysuiTestCase() { } @Test fun isAutoConfirmEnabled_featureEnabledButDisabledByThrottling() = fun isAutoConfirmEnabled_featureEnabledButDisabledByLockout() = testScope.runTest { val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled) val throttling by collectLastValue(underTest.throttling) val lockout by collectLastValue(underTest.lockout) utils.authenticationRepository.setAutoConfirmFeatureEnabled(true) // The feature is enabled. assertThat(isAutoConfirmEnabled).isTrue() // Make many wrong attempts to trigger throttling. repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) { // Make many wrong attempts to trigger lockout. repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT) { underTest.authenticate(listOf(5, 6, 7)) // Wrong PIN } assertThat(throttling).isNotNull() assertThat(lockout).isNotNull() assertThat(utils.authenticationRepository.lockoutStartedReportCount).isEqualTo(1) // Throttling disabled auto-confirm. // Lockout disabled auto-confirm. assertThat(isAutoConfirmEnabled).isFalse() // Move the clock forward one more second, to completely finish the throttling period: advanceTimeBy(FakeAuthenticationRepository.THROTTLE_DURATION_MS + 1000L) assertThat(throttling).isNull() // Move the clock forward one more second, to completely finish the lockout period: advanceTimeBy(FakeAuthenticationRepository.LOCKOUT_DURATION_MS + 1000L) assertThat(lockout).isNull() // Auto-confirm is still disabled, because throttling occurred at least once in this // Auto-confirm is still disabled, because lockout occurred at least once in this // session. assertThat(isAutoConfirmEnabled).isFalse() Loading @@ -372,66 +372,65 @@ class AuthenticationInteractorTest : SysuiTestCase() { } @Test fun throttling() = fun lockout() = testScope.runTest { val throttling by collectLastValue(underTest.throttling) val lockout by collectLastValue(underTest.lockout) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN) assertThat(throttling).isNull() assertThat(lockout).isNull() // Make many wrong attempts, but just shy of what's needed to get throttled: repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING - 1) { // Make many wrong attempts, but just shy of what's needed to get locked out: repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT - 1) { underTest.authenticate(listOf(5, 6, 7)) // Wrong PIN assertThat(throttling).isNull() assertThat(lockout).isNull() } // Make one more wrong attempt, leading to throttling: // Make one more wrong attempt, leading to lockout: underTest.authenticate(listOf(5, 6, 7)) // Wrong PIN assertThat(throttling) assertThat(lockout) .isEqualTo( AuthenticationThrottlingModel( AuthenticationLockoutModel( failedAttemptCount = FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING, remainingSeconds = FakeAuthenticationRepository.THROTTLE_DURATION_SECONDS, FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT, remainingSeconds = FakeAuthenticationRepository.LOCKOUT_DURATION_SECONDS, ) ) assertThat(utils.authenticationRepository.lockoutStartedReportCount).isEqualTo(1) // Correct PIN, but throttled, so doesn't attempt it: // Correct PIN, but locked out, so doesn't attempt it: assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)) .isEqualTo(AuthenticationResult.SKIPPED) assertThat(throttling) assertThat(lockout) .isEqualTo( AuthenticationThrottlingModel( AuthenticationLockoutModel( failedAttemptCount = FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING, remainingSeconds = FakeAuthenticationRepository.THROTTLE_DURATION_SECONDS, FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT, remainingSeconds = FakeAuthenticationRepository.LOCKOUT_DURATION_SECONDS, ) ) // Move the clock forward to ALMOST skip the throttling, leaving one second to go: val throttleTimeoutSec = FakeAuthenticationRepository.THROTTLE_DURATION_SECONDS repeat(FakeAuthenticationRepository.THROTTLE_DURATION_SECONDS - 1) { time -> // Move the clock forward to ALMOST skip the lockout, leaving one second to go: val lockoutTimeoutSec = FakeAuthenticationRepository.LOCKOUT_DURATION_SECONDS repeat(FakeAuthenticationRepository.LOCKOUT_DURATION_SECONDS - 1) { time -> advanceTimeBy(1000) assertThat(throttling) assertThat(lockout) .isEqualTo( AuthenticationThrottlingModel( AuthenticationLockoutModel( failedAttemptCount = FakeAuthenticationRepository .MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING, remainingSeconds = throttleTimeoutSec - (time + 1), FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT, remainingSeconds = lockoutTimeoutSec - (time + 1), ) ) } // Move the clock forward one more second, to completely finish the throttling period: // Move the clock forward one more second, to completely finish the lockout period: advanceTimeBy(1000) assertThat(throttling).isNull() assertThat(lockout).isNull() // Correct PIN and no longer throttled so unlocks successfully: // Correct PIN and no longer locked out so unlocks successfully: assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)) .isEqualTo(AuthenticationResult.SUCCEEDED) assertThat(throttling).isNull() assertThat(lockout).isNull() } @Test Loading packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt +17 −21 Original line number Diff line number Diff line Loading @@ -21,9 +21,9 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository import com.android.systemui.authentication.domain.interactor.AuthenticationResult import com.android.systemui.authentication.shared.model.AuthenticationLockoutModel import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel import com.android.systemui.coroutines.collectLastValue import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor import com.android.systemui.res.R Loading Loading @@ -246,46 +246,42 @@ class BouncerInteractorTest : SysuiTestCase() { } @Test fun throttling() = fun lockout() = testScope.runTest { val throttling by collectLastValue(underTest.throttling) val lockout by collectLastValue(underTest.lockout) val message by collectLastValue(underTest.message) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) assertThat(throttling).isNull() repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) { times -> assertThat(lockout).isNull() repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT) { times -> // Wrong PIN. assertThat(underTest.authenticate(listOf(6, 7, 8, 9))) .isEqualTo(AuthenticationResult.FAILED) if ( times < FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING - 1 ) { if (times < FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT - 1) { assertThat(message).isEqualTo(MESSAGE_WRONG_PIN) } } assertThat(throttling) assertThat(lockout) .isEqualTo( AuthenticationThrottlingModel( AuthenticationLockoutModel( failedAttemptCount = FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING, remainingSeconds = FakeAuthenticationRepository.THROTTLE_DURATION_SECONDS, FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT, remainingSeconds = FakeAuthenticationRepository.LOCKOUT_DURATION_SECONDS, ) ) assertTryAgainMessage( message, FakeAuthenticationRepository.THROTTLE_DURATION_MS.milliseconds.inWholeSeconds .toInt() FakeAuthenticationRepository.LOCKOUT_DURATION_MS.milliseconds.inWholeSeconds.toInt() ) // Correct PIN, but throttled, so doesn't change away from the bouncer scene: // Correct PIN, but locked out, so doesn't change away from the bouncer scene: assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)) .isEqualTo(AuthenticationResult.SKIPPED) assertTryAgainMessage( message, FakeAuthenticationRepository.THROTTLE_DURATION_MS.milliseconds.inWholeSeconds .toInt() FakeAuthenticationRepository.LOCKOUT_DURATION_MS.milliseconds.inWholeSeconds.toInt() ) throttling?.remainingSeconds?.let { seconds -> lockout?.remainingSeconds?.let { seconds -> repeat(seconds) { time -> advanceTimeBy(1000) val remainingTimeSec = seconds - time - 1 Loading @@ -295,12 +291,12 @@ class BouncerInteractorTest : SysuiTestCase() { } } assertThat(message).isEqualTo("") assertThat(throttling).isNull() assertThat(lockout).isNull() // Correct PIN and no longer throttled so changes to the Gone scene: // Correct PIN and no longer locked out so changes to the Gone scene: assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)) .isEqualTo(AuthenticationResult.SUCCEEDED) assertThat(throttling).isNull() assertThat(lockout).isNull() } @Test Loading packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt +0 −1 Original line number Diff line number Diff line Loading @@ -35,7 +35,6 @@ class AuthMethodBouncerViewModelTest : SysuiTestCase() { private val utils = SceneTestUtils(this) private val testScope = utils.testScope private val sceneInteractor = utils.sceneInteractor() private val bouncerInteractor = utils.bouncerInteractor( authenticationInteractor = utils.authenticationInteractor(), Loading packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt +13 −13 Original line number Diff line number Diff line Loading @@ -135,17 +135,17 @@ class BouncerViewModelTest : SysuiTestCase() { fun message() = testScope.runTest { val message by collectLastValue(underTest.message) val throttling by collectLastValue(bouncerInteractor.throttling) val lockout by collectLastValue(bouncerInteractor.lockout) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) assertThat(message?.isUpdateAnimated).isTrue() repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) { repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT) { // Wrong PIN. bouncerInteractor.authenticate(listOf(3, 4, 5, 6)) } assertThat(message?.isUpdateAnimated).isFalse() throttling?.remainingSeconds?.let { remainingSeconds -> lockout?.remainingSeconds?.let { remainingSeconds -> advanceTimeBy(remainingSeconds.seconds.inWholeMilliseconds) } assertThat(message?.isUpdateAnimated).isTrue() Loading @@ -160,37 +160,37 @@ class BouncerViewModelTest : SysuiTestCase() { authViewModel?.isInputEnabled ?: emptyFlow() } ) val throttling by collectLastValue(bouncerInteractor.throttling) val lockout by collectLastValue(bouncerInteractor.lockout) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) assertThat(isInputEnabled).isTrue() repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) { repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT) { // Wrong PIN. bouncerInteractor.authenticate(listOf(3, 4, 5, 6)) } assertThat(isInputEnabled).isFalse() throttling?.remainingSeconds?.let { remainingSeconds -> lockout?.remainingSeconds?.let { remainingSeconds -> advanceTimeBy(remainingSeconds.seconds.inWholeMilliseconds) } assertThat(isInputEnabled).isTrue() } @Test fun throttlingDialogMessage() = fun dialogMessage() = testScope.runTest { val throttlingDialogMessage by collectLastValue(underTest.throttlingDialogMessage) val dialogMessage by collectLastValue(underTest.dialogMessage) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) { repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT) { // Wrong PIN. assertThat(throttlingDialogMessage).isNull() assertThat(dialogMessage).isNull() bouncerInteractor.authenticate(listOf(3, 4, 5, 6)) } assertThat(throttlingDialogMessage).isNotEmpty() assertThat(dialogMessage).isNotEmpty() underTest.onThrottlingDialogDismissed() assertThat(throttlingDialogMessage).isNull() underTest.onDialogDismissed() assertThat(dialogMessage).isNull() } @Test Loading Loading
packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt +2 −2 Original line number Diff line number Diff line Loading @@ -203,7 +203,7 @@ private fun SceneScope.FoldSplittable( modifier: Modifier = Modifier, ) { val message: BouncerViewModel.MessageViewModel by viewModel.message.collectAsState() val dialogMessage: String? by viewModel.throttlingDialogMessage.collectAsState() val dialogMessage: String? by viewModel.dialogMessage.collectAsState() var dialog: Dialog? by remember { mutableStateOf(null) } val actionButton: BouncerActionButtonModel? by viewModel.actionButton.collectAsState() val splitRatio = Loading Loading @@ -320,7 +320,7 @@ private fun SceneScope.FoldSplittable( DialogInterface.BUTTON_NEUTRAL, context.getString(R.string.ok), ) { _, _ -> viewModel.onThrottlingDialogDismissed() viewModel.onDialogDismissed() } setCancelable(false) setCanceledOnTouchOutside(false) Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt +46 −47 Original line number Diff line number Diff line Loading @@ -21,9 +21,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository import com.android.systemui.authentication.shared.model.AuthenticationLockoutModel import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel import com.android.systemui.coroutines.collectLastValue import com.android.systemui.scene.SceneTestUtils import com.google.common.truth.Truth.assertThat Loading Loading @@ -76,12 +76,12 @@ class AuthenticationInteractorTest : SysuiTestCase() { @Test fun authenticate_withCorrectPin_succeeds() = testScope.runTest { val throttling by collectLastValue(underTest.throttling) val lockout by collectLastValue(underTest.lockout) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)) .isEqualTo(AuthenticationResult.SUCCEEDED) assertThat(throttling).isNull() assertThat(lockout).isNull() assertThat(utils.authenticationRepository.lockoutStartedReportCount).isEqualTo(0) } Loading Loading @@ -130,14 +130,14 @@ class AuthenticationInteractorTest : SysuiTestCase() { @Test fun authenticate_withCorrectPassword_succeeds() = testScope.runTest { val throttling by collectLastValue(underTest.throttling) val lockout by collectLastValue(underTest.lockout) utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Password ) assertThat(underTest.authenticate("password".toList())) .isEqualTo(AuthenticationResult.SUCCEEDED) assertThat(throttling).isNull() assertThat(lockout).isNull() assertThat(utils.authenticationRepository.lockoutStartedReportCount).isEqualTo(0) } Loading Loading @@ -187,7 +187,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { fun tryAutoConfirm_withAutoConfirmPinAndShorterPin_returnsNull() = testScope.runTest { val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled) val throttling by collectLastValue(underTest.throttling) val lockout by collectLastValue(underTest.lockout) utils.authenticationRepository.apply { setAuthenticationMethod(AuthenticationMethodModel.Pin) setAutoConfirmFeatureEnabled(true) Loading @@ -203,7 +203,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { ) ) .isEqualTo(AuthenticationResult.SKIPPED) assertThat(throttling).isNull() assertThat(lockout).isNull() assertThat(utils.authenticationRepository.lockoutStartedReportCount).isEqualTo(0) } Loading Loading @@ -265,7 +265,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { } @Test fun tryAutoConfirm_withAutoConfirmCorrectPinButDuringThrottling_returnsNull() = fun tryAutoConfirm_withAutoConfirmCorrectPinButDuringLockout_returnsNull() = testScope.runTest { val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled) val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked) Loading @@ -273,7 +273,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { utils.authenticationRepository.apply { setAuthenticationMethod(AuthenticationMethodModel.Pin) setAutoConfirmFeatureEnabled(true) setThrottleDuration(42) setLockoutDuration(42) } val authResult = Loading Loading @@ -334,30 +334,30 @@ class AuthenticationInteractorTest : SysuiTestCase() { } @Test fun isAutoConfirmEnabled_featureEnabledButDisabledByThrottling() = fun isAutoConfirmEnabled_featureEnabledButDisabledByLockout() = testScope.runTest { val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled) val throttling by collectLastValue(underTest.throttling) val lockout by collectLastValue(underTest.lockout) utils.authenticationRepository.setAutoConfirmFeatureEnabled(true) // The feature is enabled. assertThat(isAutoConfirmEnabled).isTrue() // Make many wrong attempts to trigger throttling. repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) { // Make many wrong attempts to trigger lockout. repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT) { underTest.authenticate(listOf(5, 6, 7)) // Wrong PIN } assertThat(throttling).isNotNull() assertThat(lockout).isNotNull() assertThat(utils.authenticationRepository.lockoutStartedReportCount).isEqualTo(1) // Throttling disabled auto-confirm. // Lockout disabled auto-confirm. assertThat(isAutoConfirmEnabled).isFalse() // Move the clock forward one more second, to completely finish the throttling period: advanceTimeBy(FakeAuthenticationRepository.THROTTLE_DURATION_MS + 1000L) assertThat(throttling).isNull() // Move the clock forward one more second, to completely finish the lockout period: advanceTimeBy(FakeAuthenticationRepository.LOCKOUT_DURATION_MS + 1000L) assertThat(lockout).isNull() // Auto-confirm is still disabled, because throttling occurred at least once in this // Auto-confirm is still disabled, because lockout occurred at least once in this // session. assertThat(isAutoConfirmEnabled).isFalse() Loading @@ -372,66 +372,65 @@ class AuthenticationInteractorTest : SysuiTestCase() { } @Test fun throttling() = fun lockout() = testScope.runTest { val throttling by collectLastValue(underTest.throttling) val lockout by collectLastValue(underTest.lockout) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN) assertThat(throttling).isNull() assertThat(lockout).isNull() // Make many wrong attempts, but just shy of what's needed to get throttled: repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING - 1) { // Make many wrong attempts, but just shy of what's needed to get locked out: repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT - 1) { underTest.authenticate(listOf(5, 6, 7)) // Wrong PIN assertThat(throttling).isNull() assertThat(lockout).isNull() } // Make one more wrong attempt, leading to throttling: // Make one more wrong attempt, leading to lockout: underTest.authenticate(listOf(5, 6, 7)) // Wrong PIN assertThat(throttling) assertThat(lockout) .isEqualTo( AuthenticationThrottlingModel( AuthenticationLockoutModel( failedAttemptCount = FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING, remainingSeconds = FakeAuthenticationRepository.THROTTLE_DURATION_SECONDS, FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT, remainingSeconds = FakeAuthenticationRepository.LOCKOUT_DURATION_SECONDS, ) ) assertThat(utils.authenticationRepository.lockoutStartedReportCount).isEqualTo(1) // Correct PIN, but throttled, so doesn't attempt it: // Correct PIN, but locked out, so doesn't attempt it: assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)) .isEqualTo(AuthenticationResult.SKIPPED) assertThat(throttling) assertThat(lockout) .isEqualTo( AuthenticationThrottlingModel( AuthenticationLockoutModel( failedAttemptCount = FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING, remainingSeconds = FakeAuthenticationRepository.THROTTLE_DURATION_SECONDS, FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT, remainingSeconds = FakeAuthenticationRepository.LOCKOUT_DURATION_SECONDS, ) ) // Move the clock forward to ALMOST skip the throttling, leaving one second to go: val throttleTimeoutSec = FakeAuthenticationRepository.THROTTLE_DURATION_SECONDS repeat(FakeAuthenticationRepository.THROTTLE_DURATION_SECONDS - 1) { time -> // Move the clock forward to ALMOST skip the lockout, leaving one second to go: val lockoutTimeoutSec = FakeAuthenticationRepository.LOCKOUT_DURATION_SECONDS repeat(FakeAuthenticationRepository.LOCKOUT_DURATION_SECONDS - 1) { time -> advanceTimeBy(1000) assertThat(throttling) assertThat(lockout) .isEqualTo( AuthenticationThrottlingModel( AuthenticationLockoutModel( failedAttemptCount = FakeAuthenticationRepository .MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING, remainingSeconds = throttleTimeoutSec - (time + 1), FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT, remainingSeconds = lockoutTimeoutSec - (time + 1), ) ) } // Move the clock forward one more second, to completely finish the throttling period: // Move the clock forward one more second, to completely finish the lockout period: advanceTimeBy(1000) assertThat(throttling).isNull() assertThat(lockout).isNull() // Correct PIN and no longer throttled so unlocks successfully: // Correct PIN and no longer locked out so unlocks successfully: assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)) .isEqualTo(AuthenticationResult.SUCCEEDED) assertThat(throttling).isNull() assertThat(lockout).isNull() } @Test Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt +17 −21 Original line number Diff line number Diff line Loading @@ -21,9 +21,9 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository import com.android.systemui.authentication.domain.interactor.AuthenticationResult import com.android.systemui.authentication.shared.model.AuthenticationLockoutModel import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel import com.android.systemui.coroutines.collectLastValue import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor import com.android.systemui.res.R Loading Loading @@ -246,46 +246,42 @@ class BouncerInteractorTest : SysuiTestCase() { } @Test fun throttling() = fun lockout() = testScope.runTest { val throttling by collectLastValue(underTest.throttling) val lockout by collectLastValue(underTest.lockout) val message by collectLastValue(underTest.message) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) assertThat(throttling).isNull() repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) { times -> assertThat(lockout).isNull() repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT) { times -> // Wrong PIN. assertThat(underTest.authenticate(listOf(6, 7, 8, 9))) .isEqualTo(AuthenticationResult.FAILED) if ( times < FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING - 1 ) { if (times < FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT - 1) { assertThat(message).isEqualTo(MESSAGE_WRONG_PIN) } } assertThat(throttling) assertThat(lockout) .isEqualTo( AuthenticationThrottlingModel( AuthenticationLockoutModel( failedAttemptCount = FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING, remainingSeconds = FakeAuthenticationRepository.THROTTLE_DURATION_SECONDS, FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT, remainingSeconds = FakeAuthenticationRepository.LOCKOUT_DURATION_SECONDS, ) ) assertTryAgainMessage( message, FakeAuthenticationRepository.THROTTLE_DURATION_MS.milliseconds.inWholeSeconds .toInt() FakeAuthenticationRepository.LOCKOUT_DURATION_MS.milliseconds.inWholeSeconds.toInt() ) // Correct PIN, but throttled, so doesn't change away from the bouncer scene: // Correct PIN, but locked out, so doesn't change away from the bouncer scene: assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)) .isEqualTo(AuthenticationResult.SKIPPED) assertTryAgainMessage( message, FakeAuthenticationRepository.THROTTLE_DURATION_MS.milliseconds.inWholeSeconds .toInt() FakeAuthenticationRepository.LOCKOUT_DURATION_MS.milliseconds.inWholeSeconds.toInt() ) throttling?.remainingSeconds?.let { seconds -> lockout?.remainingSeconds?.let { seconds -> repeat(seconds) { time -> advanceTimeBy(1000) val remainingTimeSec = seconds - time - 1 Loading @@ -295,12 +291,12 @@ class BouncerInteractorTest : SysuiTestCase() { } } assertThat(message).isEqualTo("") assertThat(throttling).isNull() assertThat(lockout).isNull() // Correct PIN and no longer throttled so changes to the Gone scene: // Correct PIN and no longer locked out so changes to the Gone scene: assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)) .isEqualTo(AuthenticationResult.SUCCEEDED) assertThat(throttling).isNull() assertThat(lockout).isNull() } @Test Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt +0 −1 Original line number Diff line number Diff line Loading @@ -35,7 +35,6 @@ class AuthMethodBouncerViewModelTest : SysuiTestCase() { private val utils = SceneTestUtils(this) private val testScope = utils.testScope private val sceneInteractor = utils.sceneInteractor() private val bouncerInteractor = utils.bouncerInteractor( authenticationInteractor = utils.authenticationInteractor(), Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt +13 −13 Original line number Diff line number Diff line Loading @@ -135,17 +135,17 @@ class BouncerViewModelTest : SysuiTestCase() { fun message() = testScope.runTest { val message by collectLastValue(underTest.message) val throttling by collectLastValue(bouncerInteractor.throttling) val lockout by collectLastValue(bouncerInteractor.lockout) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) assertThat(message?.isUpdateAnimated).isTrue() repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) { repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT) { // Wrong PIN. bouncerInteractor.authenticate(listOf(3, 4, 5, 6)) } assertThat(message?.isUpdateAnimated).isFalse() throttling?.remainingSeconds?.let { remainingSeconds -> lockout?.remainingSeconds?.let { remainingSeconds -> advanceTimeBy(remainingSeconds.seconds.inWholeMilliseconds) } assertThat(message?.isUpdateAnimated).isTrue() Loading @@ -160,37 +160,37 @@ class BouncerViewModelTest : SysuiTestCase() { authViewModel?.isInputEnabled ?: emptyFlow() } ) val throttling by collectLastValue(bouncerInteractor.throttling) val lockout by collectLastValue(bouncerInteractor.lockout) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) assertThat(isInputEnabled).isTrue() repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) { repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT) { // Wrong PIN. bouncerInteractor.authenticate(listOf(3, 4, 5, 6)) } assertThat(isInputEnabled).isFalse() throttling?.remainingSeconds?.let { remainingSeconds -> lockout?.remainingSeconds?.let { remainingSeconds -> advanceTimeBy(remainingSeconds.seconds.inWholeMilliseconds) } assertThat(isInputEnabled).isTrue() } @Test fun throttlingDialogMessage() = fun dialogMessage() = testScope.runTest { val throttlingDialogMessage by collectLastValue(underTest.throttlingDialogMessage) val dialogMessage by collectLastValue(underTest.dialogMessage) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) { repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT) { // Wrong PIN. assertThat(throttlingDialogMessage).isNull() assertThat(dialogMessage).isNull() bouncerInteractor.authenticate(listOf(3, 4, 5, 6)) } assertThat(throttlingDialogMessage).isNotEmpty() assertThat(dialogMessage).isNotEmpty() underTest.onThrottlingDialogDismissed() assertThat(throttlingDialogMessage).isNull() underTest.onDialogDismissed() assertThat(dialogMessage).isNull() } @Test Loading