Add FakeLauncherPrefs with basic tests.
Flag: TEST_ONLY
Bug: 369504330
Test: go/testedequals
Change-Id: I1cc408451b1f6e316c0ec6b087989323bcd9da4d
diff --git a/tests/multivalentTests/src/com/android/launcher3/FakeLauncherPrefs.kt b/tests/multivalentTests/src/com/android/launcher3/FakeLauncherPrefs.kt
new file mode 100644
index 0000000..058ac05
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/FakeLauncherPrefs.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024 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.launcher3
+
+import android.content.Context
+
+/** Emulates Launcher preferences for a test environment. */
+class FakeLauncherPrefs(private val context: Context) : LauncherPrefs() {
+ private val prefsMap = mutableMapOf<String, Any>()
+ private val listeners = mutableSetOf<LauncherPrefChangeListener>()
+
+ @Suppress("UNCHECKED_CAST")
+ override fun <T> get(item: ContextualItem<T>): T {
+ return prefsMap.getOrDefault(item.sharedPrefKey, item.defaultValueFromContext(context)) as T
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ override fun <T> get(item: ConstantItem<T>): T {
+ return prefsMap.getOrDefault(item.sharedPrefKey, item.defaultValue) as T
+ }
+
+ override fun put(vararg itemsToValues: Pair<Item, Any>) = putSync(*itemsToValues)
+
+ override fun <T : Any> put(item: Item, value: T) = putSync(item to value)
+
+ override fun putSync(vararg itemsToValues: Pair<Item, Any>) {
+ itemsToValues
+ .map { (i, v) -> i.sharedPrefKey to v }
+ .forEach { (k, v) ->
+ prefsMap[k] = v
+ notifyChange(k)
+ }
+ }
+
+ override fun addListener(listener: LauncherPrefChangeListener, vararg items: Item) {
+ listeners.add(listener)
+ }
+
+ override fun removeListener(listener: LauncherPrefChangeListener, vararg items: Item) {
+ listeners.remove(listener)
+ }
+
+ override fun has(vararg items: Item) = items.all { it.sharedPrefKey in prefsMap }
+
+ override fun remove(vararg items: Item) = removeSync(*items)
+
+ override fun removeSync(vararg items: Item) {
+ items
+ .filter { it.sharedPrefKey in prefsMap }
+ .forEach {
+ prefsMap.remove(it.sharedPrefKey)
+ notifyChange(it.sharedPrefKey)
+ }
+ }
+
+ override fun close() = Unit
+
+ private fun notifyChange(key: String) = listeners.forEach { it.onPrefChanged(key) }
+}
diff --git a/tests/multivalentTests/src/com/android/launcher3/FakeLauncherPrefsTest.kt b/tests/multivalentTests/src/com/android/launcher3/FakeLauncherPrefsTest.kt
new file mode 100644
index 0000000..b8e347c
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/FakeLauncherPrefsTest.kt
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2024 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.launcher3
+
+import androidx.test.core.app.ApplicationProvider.getApplicationContext
+import com.android.launcher3.util.LauncherMultivalentJUnit
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private val TEST_CONSTANT_ITEM = LauncherPrefs.nonRestorableItem("TEST_BOOLEAN_ITEM", false)
+
+private val TEST_CONTEXTUAL_ITEM =
+ ContextualItem(
+ "TEST_CONTEXTUAL_ITEM",
+ true,
+ { false },
+ EncryptionType.ENCRYPTED,
+ Boolean::class.java,
+ )
+
+@RunWith(LauncherMultivalentJUnit::class)
+class FakeLauncherPrefsTest {
+ private val launcherPrefs = FakeLauncherPrefs(getApplicationContext())
+
+ @Test
+ fun testGet_constantItemNotInPrefs_returnsDefaultValue() {
+ assertThat(launcherPrefs.get(TEST_CONSTANT_ITEM)).isFalse()
+ }
+
+ @Test
+ fun testGet_constantItemInPrefs_returnsStoredValue() {
+ launcherPrefs.put(TEST_CONSTANT_ITEM, true)
+ assertThat(launcherPrefs.get(TEST_CONSTANT_ITEM)).isTrue()
+ }
+
+ @Test
+ fun testGet_contextualItemNotInPrefs_returnsDefaultValue() {
+ assertThat(launcherPrefs.get(TEST_CONTEXTUAL_ITEM)).isFalse()
+ }
+
+ @Test
+ fun testGet_contextualItemInPrefs_returnsStoredValue() {
+ launcherPrefs.put(TEST_CONTEXTUAL_ITEM, true)
+ assertThat(launcherPrefs.get(TEST_CONTEXTUAL_ITEM)).isTrue()
+ }
+
+ @Test
+ fun testPut_multipleItems_storesAll() {
+ launcherPrefs.put(TEST_CONSTANT_ITEM to true, TEST_CONTEXTUAL_ITEM to true)
+ assertThat(launcherPrefs.get(TEST_CONSTANT_ITEM)).isTrue()
+ assertThat(launcherPrefs.get(TEST_CONTEXTUAL_ITEM)).isTrue()
+ }
+
+ @Test
+ fun testHas_itemNotInPrefs_returnsFalse() {
+ assertThat(launcherPrefs.has(TEST_CONSTANT_ITEM)).isFalse()
+ }
+
+ @Test
+ fun testHas_itemInPrefs_returnsTrue() {
+ launcherPrefs.put(TEST_CONSTANT_ITEM, true)
+ assertThat(launcherPrefs.has(TEST_CONSTANT_ITEM)).isTrue()
+ }
+
+ @Test
+ fun testHas_twoItemsWithOneInPrefs_returnsFalse() {
+ launcherPrefs.put(TEST_CONSTANT_ITEM, true)
+ assertThat(launcherPrefs.has(TEST_CONSTANT_ITEM, TEST_CONTEXTUAL_ITEM)).isFalse()
+ }
+
+ @Test
+ fun testHas_twoItemsInPrefs_returnsTrue() {
+ launcherPrefs.put(TEST_CONSTANT_ITEM to true, TEST_CONTEXTUAL_ITEM to true)
+ assertThat(launcherPrefs.has(TEST_CONSTANT_ITEM, TEST_CONTEXTUAL_ITEM)).isTrue()
+ }
+
+ @Test
+ fun testRemove_itemInPrefs_removesItem() {
+ launcherPrefs.put(TEST_CONSTANT_ITEM, true)
+ launcherPrefs.remove(TEST_CONSTANT_ITEM)
+ assertThat(launcherPrefs.has(TEST_CONSTANT_ITEM)).isFalse()
+ }
+
+ @Test
+ fun testRemove_itemsInPrefs_removesItems() {
+ launcherPrefs.put(TEST_CONSTANT_ITEM to true, TEST_CONTEXTUAL_ITEM to true)
+ launcherPrefs.remove(TEST_CONSTANT_ITEM, TEST_CONTEXTUAL_ITEM)
+ assertThat(launcherPrefs.has(TEST_CONSTANT_ITEM, TEST_CONTEXTUAL_ITEM)).isFalse()
+ }
+
+ @Test
+ fun testAddListener_changeItemInPrefs_callsListener() {
+ var changedKey: String? = null
+ launcherPrefs.addListener({ changedKey = it }, TEST_CONSTANT_ITEM)
+ launcherPrefs.put(TEST_CONSTANT_ITEM, true)
+ assertThat(changedKey).isEqualTo(TEST_CONSTANT_ITEM.sharedPrefKey)
+ }
+
+ @Test
+ fun testAddListener_removeItemFromPrefs_callsListener() {
+ var changedKey: String? = null
+ launcherPrefs.put(TEST_CONSTANT_ITEM, true)
+ launcherPrefs.addListener({ changedKey = it }, TEST_CONSTANT_ITEM)
+
+ launcherPrefs.remove(TEST_CONSTANT_ITEM)
+ assertThat(changedKey).isEqualTo(TEST_CONSTANT_ITEM.sharedPrefKey)
+ }
+
+ @Test
+ fun testRemoveListener_changeItemInPrefs_doesNotCallListener() {
+ var changedKey: String? = null
+ val listener = LauncherPrefChangeListener { changedKey = it }
+ launcherPrefs.addListener(listener, TEST_CONSTANT_ITEM)
+
+ launcherPrefs.removeListener(listener)
+ launcherPrefs.put(TEST_CONSTANT_ITEM, true)
+ assertThat(changedKey).isNull()
+ }
+}