summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
author Elliot Sisteron <elliotsisteron@google.com> 2023-07-27 17:00:23 +0000
committer Elliot Sisteron <elliotsisteron@google.com> 2023-07-28 11:17:03 +0000
commit634854be9b320c589a35b1d517227cd39cccc29e (patch)
treeedde37457c18a010daeb442aa8d473a2376c6c60 /tests
parent75aed2a34e77a1e3db24a93e14ee4ffe325ee94c (diff)
Cleanup safety_center_show_error_entries_on_timeout flag.
This one is a bit trickier because tests rely on this in multiple ways: - UI tests want to ensure that the data on the screen doesn't change, however a refresh is triggered on page open and most tests set the data manually rather than using the receiver to do so. The timeout could set error on UI entries in the middle of the test, which isn't ideal. Worked around this by setting the refresh timeout to the test timeout. - Some existing tests were actively checking the behavior of that flag and using the error listener as an easy way to check for timeouts. I think it's a good thing to cleanup this flag regardless, as we ideally want to have tests matching the production behavior, which wasn't the case here (the flag was set to false in tests, but true in production code). Bug: 289788052 Test: SafetyCenter tests Relnote: N/A Change-Id: I1f9dc8749d46f437c8dfbb98228ed1f042ee5821
Diffstat (limited to 'tests')
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt37
-rw-r--r--tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt7
-rw-r--r--tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterManagerTest.kt15
-rw-r--r--tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetySourceStateCollectedLoggingHelperTests.kt11
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/Coroutines.kt6
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterFlags.kt21
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestListener.kt65
7 files changed, 95 insertions, 67 deletions
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
index 6cd24f800..298d7643c 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
@@ -1111,11 +1111,11 @@ class SafetyCenterManagerTest {
)
// Because wrong ID, refresh hasn't finished. Wait for timeout.
- listener.receiveSafetyCenterErrorDetails()
+ listener.waitForSafetyCenterRefresh(withErrorEntry = true)
SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_LONG)
SafetySourceReceiver.setResponse(
- Request.Rescan(SINGLE_SOURCE_ID),
+ Request.Refresh(SINGLE_SOURCE_ID),
Response.SetData(safetySourceTestData.information)
)
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
@@ -1185,7 +1185,7 @@ class SafetyCenterManagerTest {
safetyCenterManager.getSafetySourceDataWithPermission(SINGLE_SOURCE_ID)
assertThat(apiSafetySourceData1).isNull()
// Wait for the ongoing refresh to timeout.
- listener.receiveSafetyCenterErrorDetails()
+ listener.waitForSafetyCenterRefresh(withErrorEntry = true)
SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_LONG)
SafetySourceReceiver.setResponse(
Request.Refresh(SINGLE_SOURCE_ID),
@@ -1237,18 +1237,11 @@ class SafetyCenterManagerTest {
REFRESH_REASON_RESCAN_BUTTON_CLICK
)
- val safetyCenterErrorDetailsFromListener = listener.receiveSafetyCenterErrorDetails()
- assertThat(safetyCenterErrorDetailsFromListener)
- .isEqualTo(
- SafetyCenterErrorDetails(
- safetyCenterResourcesApk.getStringByName("refresh_timeout")
- )
- )
+ listener.waitForSafetyCenterRefresh(withErrorEntry = true)
}
@Test
fun refreshSafetySources_withUntrackedSourceThatTimesOut_doesNotTimeOut() {
- SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_SHORT)
SafetyCenterFlags.untrackedSources = setOf(SOURCE_ID_1)
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesConfig)
// SOURCE_ID_1 will timeout
@@ -1264,14 +1257,11 @@ class SafetyCenterManagerTest {
REFRESH_REASON_RESCAN_BUTTON_CLICK
)
- assertFailsWith(TimeoutCancellationException::class) {
- listener.receiveSafetyCenterErrorDetails(TIMEOUT_SHORT)
- }
+ listener.waitForSafetyCenterRefresh(withErrorEntry = false)
}
@Test
fun refreshSafetySources_withMultipleUntrackedSourcesThatTimeOut_doesNotTimeOut() {
- SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_SHORT)
SafetyCenterFlags.untrackedSources = setOf(SOURCE_ID_1, SOURCE_ID_2)
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesConfig)
// SOURCE_ID_1 and SOURCE_ID_2 will timeout
@@ -1285,9 +1275,7 @@ class SafetyCenterManagerTest {
REFRESH_REASON_RESCAN_BUTTON_CLICK
)
- assertFailsWith(TimeoutCancellationException::class) {
- listener.receiveSafetyCenterErrorDetails(TIMEOUT_SHORT)
- }
+ listener.waitForSafetyCenterRefresh(withErrorEntry = false)
}
@Test
@@ -1301,25 +1289,20 @@ class SafetyCenterManagerTest {
REFRESH_REASON_RESCAN_BUTTON_CLICK
)
- val safetyCenterErrorDetailsFromListener = listener.receiveSafetyCenterErrorDetails()
- assertThat(safetyCenterErrorDetailsFromListener)
- .isEqualTo(
- SafetyCenterErrorDetails(
- safetyCenterResourcesApk.getStringByName("refresh_timeout")
- )
- )
+ listener.waitForSafetyCenterRefresh(withErrorEntry = true)
}
@Test
fun refreshSafetySources_withTrackedSourceThatHasNoReceiver_doesNotTimeOut() {
- SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_SHORT)
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceOtherPackageConfig)
val listener = safetyCenterTestHelper.addListener()
safetyCenterManager.refreshSafetySourcesWithPermission(REFRESH_REASON_RESCAN_BUTTON_CLICK)
assertFailsWith(TimeoutCancellationException::class) {
- listener.receiveSafetyCenterErrorDetails(TIMEOUT_SHORT)
+ // In this case a refresh isn't even started because there is only a single source
+ // without a receiver.
+ listener.receiveSafetyCenterData(TIMEOUT_SHORT)
}
}
diff --git a/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt b/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt
index de7a18c0e..9534b597a 100644
--- a/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt
+++ b/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt
@@ -35,8 +35,6 @@ import android.safetycenter.SafetyCenterIssue
import android.safetycenter.SafetyCenterManager
import android.safetycenter.SafetyCenterStaticEntry
import android.safetycenter.SafetyCenterStaticEntryGroup
-import android.safetycenter.SafetyCenterStatus.REFRESH_STATUS_DATA_FETCH_IN_PROGRESS
-import android.safetycenter.SafetyCenterStatus.REFRESH_STATUS_NONE
import android.safetycenter.SafetyEvent
import android.safetycenter.SafetySourceData
import androidx.test.core.app.ApplicationProvider
@@ -1279,10 +1277,7 @@ class SafetyCenterMultiUsersTest {
private fun disableQuietModeAndWaitForRefreshToComplete() {
val listener = safetyCenterTestHelper.addListener()
deviceState.workProfile().setQuietMode(false)
- listener.receiveSafetyCenterData {
- it.status.refreshStatus == REFRESH_STATUS_DATA_FETCH_IN_PROGRESS
- }
- listener.receiveSafetyCenterData { it.status.refreshStatus == REFRESH_STATUS_NONE }
+ listener.waitForSafetyCenterRefresh()
}
private fun safetyCenterEntryOkForWork(sourceId: String, managedUserId: Int) =
diff --git a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterManagerTest.kt b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterManagerTest.kt
index 0c952ede2..e2a7802b3 100644
--- a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterManagerTest.kt
+++ b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterManagerTest.kt
@@ -766,9 +766,8 @@ class SafetyCenterManagerTest {
@get:Rule(order = 2) val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
@Test
- fun refreshSafetySources_withShowEntriesOnTimeout_marksSafetySourceAsError() {
+ fun refreshSafetySources_timeout_marksSafetySourceAsError() {
SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_SHORT)
- SafetyCenterFlags.showErrorEntriesOnTimeout = true
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
val listener = safetyCenterTestHelper.addListener()
@@ -786,9 +785,8 @@ class SafetyCenterManagerTest {
}
@Test
- fun refreshSafetySources_withShowEntriesOnTimeout_keepsShowingErrorUntilClearedBySource() {
+ fun refreshSafetySources_timeout_keepsShowingErrorUntilClearedBySource() {
SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_SHORT)
- SafetyCenterFlags.showErrorEntriesOnTimeout = true
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
val listener = safetyCenterTestHelper.addListener()
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
@@ -816,18 +814,15 @@ class SafetyCenterManagerTest {
}
@Test
- fun refreshSafetySources_withShowEntriesOnTimeout_doesntSetErrorForBackgroundRefreshes() {
+ fun refreshSafetySources_timeout_doesntSetErrorForBackgroundRefreshes() {
SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_SHORT)
- SafetyCenterFlags.showErrorEntriesOnTimeout = true
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
val listener = safetyCenterTestHelper.addListener()
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(REFRESH_REASON_OTHER)
- val safetyCenterBeforeTimeout = listener.receiveSafetyCenterData()
- assertThat(safetyCenterBeforeTimeout.status.refreshStatus)
- .isEqualTo(REFRESH_STATUS_DATA_FETCH_IN_PROGRESS)
- val safetyCenterDataAfterTimeout = listener.receiveSafetyCenterData()
+ val safetyCenterDataAfterTimeout =
+ listener.waitForSafetyCenterRefresh(withErrorEntry = false)
assertThat(safetyCenterDataAfterTimeout).isEqualTo(safetyCenterDataFromConfig)
}
diff --git a/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetySourceStateCollectedLoggingHelperTests.kt b/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetySourceStateCollectedLoggingHelperTests.kt
index 9e3a33018..d020aac0a 100644
--- a/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetySourceStateCollectedLoggingHelperTests.kt
+++ b/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetySourceStateCollectedLoggingHelperTests.kt
@@ -18,9 +18,6 @@ package android.safetycenter.hostside.device
import android.content.Context
import android.safetycenter.SafetyCenterManager
-import android.safetycenter.SafetyCenterStatus
-import android.safetycenter.SafetyCenterStatus.REFRESH_STATUS_DATA_FETCH_IN_PROGRESS
-import android.safetycenter.SafetyCenterStatus.REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS
import android.safetycenter.SafetyEvent
import android.safetycenter.SafetySourceErrorDetails
import androidx.test.core.app.ApplicationProvider
@@ -168,12 +165,6 @@ class SafetySourceStateCollectedLoggingHelperTests {
// things are logged.
val listener = safetyCenterTestHelper.addListener()
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(refreshReason)
- listener.receiveSafetyCenterData {
- it.status.refreshStatus == REFRESH_STATUS_DATA_FETCH_IN_PROGRESS ||
- it.status.refreshStatus == REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS
- }
- listener.receiveSafetyCenterData {
- it.status.refreshStatus == SafetyCenterStatus.REFRESH_STATUS_NONE
- }
+ listener.waitForSafetyCenterRefresh()
}
}
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/Coroutines.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/Coroutines.kt
index 6c6336da3..a7009b19e 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/Coroutines.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/Coroutines.kt
@@ -30,7 +30,11 @@ import kotlinx.coroutines.withTimeoutOrNull
/** A class that facilitates interacting with coroutines. */
object Coroutines {
- private val TEST_TIMEOUT: Duration
+ /**
+ * The timeout of a test case, typically varies depending on whether the test is running
+ * locally, on pre-submit or post-submit.
+ */
+ val TEST_TIMEOUT: Duration
get() =
Duration.ofMillis(
InstrumentationRegistry.getArguments().getString("timeout_msec", "60000").toLong()
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterFlags.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterFlags.kt
index 28b621d5c..5cc2e3c8e 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterFlags.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterFlags.kt
@@ -34,6 +34,7 @@ import android.safetycenter.SafetyCenterManager.REFRESH_REASON_RESCAN_BUTTON_CLI
import android.safetycenter.SafetyCenterManager.REFRESH_REASON_SAFETY_CENTER_ENABLED
import android.safetycenter.SafetySourceData
import com.android.modules.utils.build.SdkLevel
+import com.android.safetycenter.testing.Coroutines.TEST_TIMEOUT
import com.android.safetycenter.testing.Coroutines.TIMEOUT_LONG
import com.android.safetycenter.testing.ShellPermissions.callWithShellPermissionIdentity
import java.time.Duration
@@ -100,13 +101,6 @@ object SafetyCenterFlags {
DurationParser()
)
- /**
- * Flag that determines whether we should show error entries for sources that timeout when
- * refreshing them.
- */
- private val showErrorEntriesOnTimeoutFlag =
- Flag("safety_center_show_error_entries_on_timeout", defaultValue = false, BooleanParser())
-
/** Flag that determines whether we should replace the IconAction of the lock screen source. */
private val replaceLockScreenIconActionFlag =
Flag("safety_center_replace_lock_screen_icon_action", defaultValue = true, BooleanParser())
@@ -115,11 +109,16 @@ object SafetyCenterFlags {
* Flag that determines the time for which a Safety Center refresh is allowed to wait for a
* source to respond to a refresh request before timing out and marking the refresh as finished,
* depending on the refresh reason.
+ *
+ * Unlike the production code, this flag is set to [TEST_TIMEOUT] for all refresh reasons by
+ * default for convenience. UI tests typically will set some data manually rather than going
+ * through a full refresh, and we don't want to timeout the refresh and potentially end up with
+ * error entries in this case (as it could lead to flakyness).
*/
private val refreshSourceTimeoutsFlag =
Flag(
"safety_center_refresh_sources_timeouts_millis",
- defaultValue = getAllRefreshTimeoutsMap(TIMEOUT_LONG),
+ defaultValue = getAllRefreshTimeoutsMap(TEST_TIMEOUT),
MapParser(IntParser(), DurationParser())
)
@@ -302,7 +301,6 @@ object SafetyCenterFlags {
notificationsMinDelayFlag,
immediateNotificationBehaviorIssuesFlag,
notificationResurfaceIntervalFlag,
- showErrorEntriesOnTimeoutFlag,
replaceLockScreenIconActionFlag,
refreshSourceTimeoutsFlag,
resolveActionTimeoutFlag,
@@ -341,14 +339,11 @@ object SafetyCenterFlags {
/** A property that allows getting and setting the [notificationResurfaceIntervalFlag]. */
var notificationResurfaceInterval: Duration by notificationResurfaceIntervalFlag
- /** A property that allows getting and setting the [showErrorEntriesOnTimeoutFlag]. */
- var showErrorEntriesOnTimeout: Boolean by showErrorEntriesOnTimeoutFlag
-
/** A property that allows getting and setting the [replaceLockScreenIconActionFlag]. */
var replaceLockScreenIconAction: Boolean by replaceLockScreenIconActionFlag
/** A property that allows getting and setting the [refreshSourceTimeoutsFlag]. */
- var refreshTimeouts: Map<Int, Duration> by refreshSourceTimeoutsFlag
+ private var refreshTimeouts: Map<Int, Duration> by refreshSourceTimeoutsFlag
/** A property that allows getting and setting the [resolveActionTimeoutFlag]. */
var resolveActionTimeout: Duration by resolveActionTimeoutFlag
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestListener.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestListener.kt
index 624c32d5f..8ce5c25d4 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestListener.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestListener.kt
@@ -18,9 +18,14 @@ package com.android.safetycenter.testing
import android.os.Build.VERSION_CODES.TIRAMISU
import android.safetycenter.SafetyCenterData
+import android.safetycenter.SafetyCenterEntry
import android.safetycenter.SafetyCenterErrorDetails
import android.safetycenter.SafetyCenterManager.OnSafetyCenterDataChangedListener
+import android.safetycenter.SafetyCenterStaticEntry
+import android.safetycenter.SafetyCenterStatus
+import android.text.TextUtils
import androidx.annotation.RequiresApi
+import androidx.test.core.app.ApplicationProvider.getApplicationContext
import com.android.safetycenter.testing.Coroutines.TIMEOUT_LONG
import com.android.safetycenter.testing.Coroutines.runBlockingWithTimeout
import java.time.Duration
@@ -64,6 +69,47 @@ class SafetyCenterTestListener : OnSafetyCenterDataChangedListener {
}
/**
+ * Waits for a full Safety Center refresh to complete, where each change to the underlying
+ * [SafetyCenterData] must happen within the given [timeout].
+ *
+ * @param withErrorEntry optionally check whether we should expect the [SafetyCenterData] to
+ * have or not have at least one an error entry after the refresh completes
+ * @return the [SafetyCenterData] after the refresh completes
+ */
+ fun waitForSafetyCenterRefresh(
+ timeout: Duration = TIMEOUT_LONG,
+ withErrorEntry: Boolean? = null
+ ): SafetyCenterData {
+ receiveSafetyCenterData(timeout) {
+ it.status.refreshStatus == SafetyCenterStatus.REFRESH_STATUS_DATA_FETCH_IN_PROGRESS ||
+ it.status.refreshStatus == SafetyCenterStatus.REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS
+ }
+ val afterRefresh =
+ receiveSafetyCenterData(timeout) {
+ it.status.refreshStatus == SafetyCenterStatus.REFRESH_STATUS_NONE
+ }
+ if (withErrorEntry == null) {
+ return afterRefresh
+ }
+ val errorMessage =
+ SafetyCenterTestData(getApplicationContext())
+ .getRefreshErrorString(numberOfErrorEntries = 1)
+ val containsErrorEntry = afterRefresh.containsAnyEntryWithSummary(errorMessage)
+ if (withErrorEntry && !containsErrorEntry) {
+ throw AssertionError(
+ "No error entry with message: \"$errorMessage\" found in SafetyCenterData" +
+ " after refresh: $afterRefresh"
+ )
+ } else if (!withErrorEntry && containsErrorEntry) {
+ throw AssertionError(
+ "Found an error entry with message: \"$errorMessage\" in SafetyCenterData" +
+ " after refresh: $afterRefresh"
+ )
+ }
+ return afterRefresh
+ }
+
+ /**
* Waits for a [SafetyCenterErrorDetails] update from SafetyCenter within the given [timeout].
*/
fun receiveSafetyCenterErrorDetails(timeout: Duration = TIMEOUT_LONG) =
@@ -74,4 +120,23 @@ class SafetyCenterTestListener : OnSafetyCenterDataChangedListener {
dataChannel.cancel()
errorChannel.cancel()
}
+
+ private companion object {
+ fun SafetyCenterData.containsAnyEntryWithSummary(summary: CharSequence): Boolean =
+ entries().any { TextUtils.equals(it.summary, summary) } ||
+ staticEntries().any { TextUtils.equals(it.summary, summary) }
+
+ fun SafetyCenterData.entries(): List<SafetyCenterEntry> =
+ entriesOrGroups.flatMap {
+ val entry = it.entry
+ if (entry != null) {
+ listOf(entry)
+ } else {
+ it.entryGroup!!.entries
+ }
+ }
+
+ fun SafetyCenterData.staticEntries(): List<SafetyCenterStaticEntry> =
+ staticEntryGroups.flatMap { it.staticEntries }
+ }
}