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
This commit is contained in:
@@ -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"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user