diff options
| author | 2022-11-14 16:03:49 -0800 | |
|---|---|---|
| committer | 2022-11-15 15:46:27 -0800 | |
| commit | 038616a71a9dea85f70eabbbd9486a67c55e82e6 (patch) | |
| tree | c95f886ff54d08998b94d71ae7c02e11bb1fef49 | |
| parent | 6fe4159252d2e5aa1a41b129f4de0f95c07fecbd (diff) | |
Unit test for quick affordance content provider.
For merging and app bloat reasons, this test ended up being removed from
the original CL that was submitted.
Bug: 254857637
Test: this is a test
Change-Id: I40ce21840a302949d02a18ecf05d6a2cec2ab2f5
| -rw-r--r-- | packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProviderTest.kt | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProviderTest.kt new file mode 100644 index 000000000000..ed08849fe70c --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProviderTest.kt @@ -0,0 +1,399 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.android.systemui.keyguard + +import android.content.ContentValues +import android.content.pm.PackageManager +import android.content.pm.ProviderInfo +import androidx.test.filters.SmallTest +import com.android.internal.widget.LockPatternUtils +import com.android.systemui.SystemUIAppComponentFactoryBase +import com.android.systemui.SysuiTestCase +import com.android.systemui.flags.FakeFeatureFlags +import com.android.systemui.flags.Flags +import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig +import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager +import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository +import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor +import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.settings.UserTracker +import com.android.systemui.shared.keyguard.data.content.KeyguardQuickAffordanceProviderContract as Contract +import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots +import com.android.systemui.statusbar.policy.KeyguardStateController +import com.android.systemui.util.mockito.mock +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(JUnit4::class) +class KeyguardQuickAffordanceProviderTest : SysuiTestCase() { + + @Mock private lateinit var lockPatternUtils: LockPatternUtils + @Mock private lateinit var keyguardStateController: KeyguardStateController + @Mock private lateinit var userTracker: UserTracker + @Mock private lateinit var activityStarter: ActivityStarter + + private lateinit var underTest: KeyguardQuickAffordanceProvider + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + underTest = KeyguardQuickAffordanceProvider() + val quickAffordanceRepository = + KeyguardQuickAffordanceRepository( + appContext = context, + scope = CoroutineScope(IMMEDIATE), + backgroundDispatcher = IMMEDIATE, + selectionManager = KeyguardQuickAffordanceSelectionManager(), + configs = + setOf( + FakeKeyguardQuickAffordanceConfig( + key = AFFORDANCE_1, + pickerIconResourceId = 1, + ), + FakeKeyguardQuickAffordanceConfig( + key = AFFORDANCE_2, + pickerIconResourceId = 2, + ), + ), + ) + underTest.interactor = + KeyguardQuickAffordanceInteractor( + keyguardInteractor = + KeyguardInteractor( + repository = FakeKeyguardRepository(), + ), + registry = mock(), + lockPatternUtils = lockPatternUtils, + keyguardStateController = keyguardStateController, + userTracker = userTracker, + activityStarter = activityStarter, + featureFlags = + FakeFeatureFlags().apply { + set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, true) + }, + repository = { quickAffordanceRepository }, + ) + + underTest.attachInfoForTesting( + context, + ProviderInfo().apply { authority = Contract.AUTHORITY }, + ) + context.contentResolver.addProvider(Contract.AUTHORITY, underTest) + context.testablePermissions.setPermission( + Contract.PERMISSION, + PackageManager.PERMISSION_GRANTED, + ) + } + + @Test + fun `onAttachInfo - reportsContext`() { + val callback: SystemUIAppComponentFactoryBase.ContextAvailableCallback = mock() + underTest.setContextAvailableCallback(callback) + + underTest.attachInfo(context, null) + + verify(callback).onContextAvailable(context) + } + + @Test + fun getType() { + assertThat(underTest.getType(Contract.AffordanceTable.URI)) + .isEqualTo( + "vnd.android.cursor.dir/vnd." + + "${Contract.AUTHORITY}.${Contract.AffordanceTable.TABLE_NAME}" + ) + assertThat(underTest.getType(Contract.SlotTable.URI)) + .isEqualTo( + "vnd.android.cursor.dir/vnd.${Contract.AUTHORITY}.${Contract.SlotTable.TABLE_NAME}" + ) + assertThat(underTest.getType(Contract.SelectionTable.URI)) + .isEqualTo( + "vnd.android.cursor.dir/vnd." + + "${Contract.AUTHORITY}.${Contract.SelectionTable.TABLE_NAME}" + ) + } + + @Test + fun `insert and query selection`() = + runBlocking(IMMEDIATE) { + val slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START + val affordanceId = AFFORDANCE_2 + + insertSelection( + slotId = slotId, + affordanceId = affordanceId, + ) + + assertThat(querySelections()) + .isEqualTo( + listOf( + Selection( + slotId = slotId, + affordanceId = affordanceId, + ) + ) + ) + } + + @Test + fun `query slots`() = + runBlocking(IMMEDIATE) { + assertThat(querySlots()) + .isEqualTo( + listOf( + Slot( + id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, + capacity = 1, + ), + Slot( + id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, + capacity = 1, + ), + ) + ) + } + + @Test + fun `query affordances`() = + runBlocking(IMMEDIATE) { + assertThat(queryAffordances()) + .isEqualTo( + listOf( + Affordance( + id = AFFORDANCE_1, + name = AFFORDANCE_1, + iconResourceId = 1, + ), + Affordance( + id = AFFORDANCE_2, + name = AFFORDANCE_2, + iconResourceId = 2, + ), + ) + ) + } + + @Test + fun `delete and query selection`() = + runBlocking(IMMEDIATE) { + insertSelection( + slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, + affordanceId = AFFORDANCE_1, + ) + insertSelection( + slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, + affordanceId = AFFORDANCE_2, + ) + + context.contentResolver.delete( + Contract.SelectionTable.URI, + "${Contract.SelectionTable.Columns.SLOT_ID} = ? AND" + + " ${Contract.SelectionTable.Columns.AFFORDANCE_ID} = ?", + arrayOf( + KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, + AFFORDANCE_2, + ), + ) + + assertThat(querySelections()) + .isEqualTo( + listOf( + Selection( + slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, + affordanceId = AFFORDANCE_1, + ) + ) + ) + } + + @Test + fun `delete all selections in a slot`() = + runBlocking(IMMEDIATE) { + insertSelection( + slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, + affordanceId = AFFORDANCE_1, + ) + insertSelection( + slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, + affordanceId = AFFORDANCE_2, + ) + + context.contentResolver.delete( + Contract.SelectionTable.URI, + Contract.SelectionTable.Columns.SLOT_ID, + arrayOf( + KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, + ), + ) + + assertThat(querySelections()) + .isEqualTo( + listOf( + Selection( + slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, + affordanceId = AFFORDANCE_1, + ) + ) + ) + } + + private fun insertSelection( + slotId: String, + affordanceId: String, + ) { + context.contentResolver.insert( + Contract.SelectionTable.URI, + ContentValues().apply { + put(Contract.SelectionTable.Columns.SLOT_ID, slotId) + put(Contract.SelectionTable.Columns.AFFORDANCE_ID, affordanceId) + } + ) + } + + private fun querySelections(): List<Selection> { + return context.contentResolver + .query( + Contract.SelectionTable.URI, + null, + null, + null, + null, + ) + ?.use { cursor -> + buildList { + val slotIdColumnIndex = + cursor.getColumnIndex(Contract.SelectionTable.Columns.SLOT_ID) + val affordanceIdColumnIndex = + cursor.getColumnIndex(Contract.SelectionTable.Columns.AFFORDANCE_ID) + if (slotIdColumnIndex == -1 || affordanceIdColumnIndex == -1) { + return@buildList + } + + while (cursor.moveToNext()) { + add( + Selection( + slotId = cursor.getString(slotIdColumnIndex), + affordanceId = cursor.getString(affordanceIdColumnIndex), + ) + ) + } + } + } + ?: emptyList() + } + + private fun querySlots(): List<Slot> { + return context.contentResolver + .query( + Contract.SlotTable.URI, + null, + null, + null, + null, + ) + ?.use { cursor -> + buildList { + val idColumnIndex = cursor.getColumnIndex(Contract.SlotTable.Columns.ID) + val capacityColumnIndex = + cursor.getColumnIndex(Contract.SlotTable.Columns.CAPACITY) + if (idColumnIndex == -1 || capacityColumnIndex == -1) { + return@buildList + } + + while (cursor.moveToNext()) { + add( + Slot( + id = cursor.getString(idColumnIndex), + capacity = cursor.getInt(capacityColumnIndex), + ) + ) + } + } + } + ?: emptyList() + } + + private fun queryAffordances(): List<Affordance> { + return context.contentResolver + .query( + Contract.AffordanceTable.URI, + null, + null, + null, + null, + ) + ?.use { cursor -> + buildList { + val idColumnIndex = cursor.getColumnIndex(Contract.AffordanceTable.Columns.ID) + val nameColumnIndex = + cursor.getColumnIndex(Contract.AffordanceTable.Columns.NAME) + val iconColumnIndex = + cursor.getColumnIndex(Contract.AffordanceTable.Columns.ICON) + if (idColumnIndex == -1 || nameColumnIndex == -1 || iconColumnIndex == -1) { + return@buildList + } + + while (cursor.moveToNext()) { + add( + Affordance( + id = cursor.getString(idColumnIndex), + name = cursor.getString(nameColumnIndex), + iconResourceId = cursor.getInt(iconColumnIndex), + ) + ) + } + } + } + ?: emptyList() + } + + data class Slot( + val id: String, + val capacity: Int, + ) + + data class Affordance( + val id: String, + val name: String, + val iconResourceId: Int, + ) + + data class Selection( + val slotId: String, + val affordanceId: String, + ) + + companion object { + private val IMMEDIATE = Dispatchers.Main.immediate + private const val AFFORDANCE_1 = "affordance_1" + private const val AFFORDANCE_2 = "affordance_2" + } +} |